mysql:数据库索引
索引概念和作用
b树和b+树区别
innodb支持哪两种索引
b+树结构
b+树缺点
b+树优点
聚集索引和非聚集索引区别
聚集索引相关问题
索引使用的最佳实践
===?索引的概念?为什么要用索引呢?不用索引的话查询一个数据会扫描整张表吗?
索引是一种数据结构,相当于数据的目录,存储了指向数据的指针。
不用索引,那么会扫描整张表再查出符合的数据。
有了索引,能够加快数据查询的速度。
====b树和b+树的区别
b树不论叶子结点还是分支节点都存储了数据。
b+树所有的数据都存储在叶子节点里面,分支节点都用来做为索引。
===innodb支持哪两种索引?
第一种哈希索引,会根据表情况自动创建哈希索引,哈希索引底层使用散列表加链表组合的结构,散列算法使用简单的除数取余法。
第二种b+树索引,会找到对应键值的记录所在的数据页,将数据页读入内存中查找相应的数据。
===b+树结构
B+树首先是个平衡搜索树,但是每个节点可以有多个子节点,每个节点可以存储多个键值和指向子节点的指针。
所有的数据都存在叶子节点中,按照顺序进行排列,是一种双向链表的结构。查询某行数据时会加载整个数据页到内存中再定位。
===B+树索引的缺点
B+树的缺点就是:因为维护数据的顺序,所以在插入或者删除数据的时候难以避免的需要对索引进行调整,就会涉及到分页拆页等等磁盘操作。
===B+树的优点
===高扇出性?
B+树一个节点可以有多个子节点也就是子树。所以高度维护在2到3层,所以查询某行记录只要2到3次io就可以了。
===顺序存储?
查询效率很高。
===覆盖索引
查主键不需要查到叶子结点直接通过非叶子节点查,利用覆盖索引加快查询的速率。
===innodb中的聚集索引和非聚集索引区别?
都是使用b+树,但是非聚集索引的叶子节点不存数据,存的还是键值和指针。
因为在innodb中数据都是存储在聚集索引中的,所以使用非聚集索引最后还是需要通过聚集索引才能够找到数据。
===为什么一张表只能够有一个聚簇索引呢?
聚簇索引要求索引顺序和数据存储顺序一致,也就是相邻键值的数据行都存储在一起。因为数据只存储一份,所以不能有两个聚簇索引。
===innodb默认为主键创建聚簇索引,那么如果没有主键呢?
如果没有定义主键,innodb会选择一个非空索引代替,如果没有非空索引,就隐式定一个主键。
===聚簇索引有什么优势呢?
1.相关的数据可以保存在一起。比如保存用户邮件,用户id相同的数据都保存在一起可能是一个数据页,这样磁盘io就一次。否则不用聚簇索引可能导致磁盘多次io。
2.数据访问速度更快。聚簇索引把索引和数据放在同一个b-tree中,可以直接访问到数据。
3.可以使用覆盖索引。只扫描索引不扫描数据加快扫描的速度。
===聚簇索引使用自增的int类型的id做主键对比使用varchar类型主键的优势所在?
使用int类型的主键的时候,按照顺序插入新的数据行,到达表的15/16的时候写到新的页中。因为是顺序插入,速度极快。
使用varchar类型主键,不能保证新插入的数据行的逻辑顺序在旧行之后,可能插入到中间,这就可能出现分页和碎片。总结的缺点如下:
1.因为可能插入到之前的数据页,如果之前的数据页已经刷盘了,从缓存中移除了,就可能重新从磁盘中io读取到缓存中。这就是随机io。
2.写入是乱序的,可能导致分页,需要移动大量数据。同时带来碎片。
索引的使用和优化:
===?索引的数据类型选择的三个原则,也就是用什么类型的字段作为索引呢?
1.选小的数据类型。
2.选整形不选字符型,选日期不选字符串。
3.避免使用NULL
===?mysql如何存储ip,使用varchar存还是使用int存呢?
使用int存更快,只要用函数做一系列的转化就可以了。
select inet_aton('255.255.255.255');
select inet_ntoa(4294967295);
===?为什么最好不要给字符串添加索引呢?
字符串都是随机的,所以它们在索引中的位置也是随机的,这会导致页面分裂、随机访问磁盘,聚簇索引分裂(对于使用聚簇索引的存储引擎)。
===如何使用索引总结。
索引分单列多列索引。
单列可以有不同字段索引,整形的或者字符型的。主键一般使用整形做索引,也就是整形的聚集索引,因为聚集索引的索引顺序和数据存储顺序一致,用整形可以顺序插入,如果用字符型就可能随机插入造成分页碎片的问题。
多列索引要注意把选择性高的字段尽量放在前面,选择性的算法就是将字段不同的数据行数量除以总的数据量得到选择性。其次要注意多列索引的使用方式,往前的列必须要精确匹配,比如三个字段做的一个索引举例。
最后是覆盖索引的用法,覆盖索引只查索引就拿到数据,不用查最后的叶子节点,大大加快查询的速度。举例>80000的十个id。
===组合索引的使用方法
组合索引使用规则是: 从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用;
某个字段用在where条件中时候,有这么几种使用方式:
1.精确匹配,where id = …,模糊匹配 where id like ‘%andy…’
2.范围查找,where id < …
范围查询相当于一个断点。
(0) select * from mytable where a=3 and b=5 and c=4;
abc三个索引都在where条件里面用到了,而且都发挥了作用
(1) select * from mytable where c=4 and b=6 and a=3;
这条语句列出来只想说明 mysql没有那么笨,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样
(2) select * from mytable where a=3 and c=7;
a用到索引,b没有用,所以c是没有用到索引效果的
(3) select * from mytable where a=3 and b>7 and c=3;
a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引
(4) select * from mytable where b=3 and c=4;
因为a索引没有使用,所以这里 bc都没有用上索引效果
(5) select * from mytable where a>4 and b=7 and c=9;
a用到了 b没有使用,c没有使用
(6) select * from mytable where a=3 order by b;
a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的
(7) select * from mytable where a=3 order by c;
a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort
(8) select * from mytable where b=3 order by a;
b没有用到索引,排序中a也没有发挥索引效果
===组合索引的使用技巧
对于选择性很低但是频繁使用到的比如性别这种字段可以放在多字段索引的靠前位置。只是查询的时候多加一句sex in (f,m)这样查询不限制男女并且符合多字段索引的使用规则。
某个字段需要做范围查询,尽量放在最后,因为范围查询之后的字段不会用到索引。