目录
一、(InnoDB下MySQL)索引的实现原理
索引的实现经历了 3 个阶段的升级:⼆叉树、 B 树、 B+ 树。
1、二叉树阶段:
缺点:数据⼤之后树很⾼,维护和查询的性能不好。
2、B树阶段:
缺点:将所有数据都存储在叶子节点和非叶子节点,当数据量特别大的时候,光把索引加载起来就需要很长很长的时间。
3、B+树阶段:
优化:只有叶⼦节点才存储数据,且数据和索引是分离的,所谓的存储的数据,其实是指向数据的地址,数据量变的⾮常⼩。
二、必问的面试问题:聚簇索引/聚集索引/主键索引和非聚簇索引/二级索引/非聚集索引的区别。
每个索引都会对应一颗B+树
表中 R1~R5 的 (ID,k) 值分别为 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6),两棵树的示例示意图如下:
聚簇索引时只要查询到对应的id就能直接得到id对应的这一行数据。(只有主键索引的叶子节点才存储的是数据的内存地址,其他索引的叶子节点存储的都是主键信息)
从上述图⽚可以看出,聚簇索引叶⼦节点存储的是表的⾏数据内容(内存地址),所以可以直接返回结果;⽽⾮聚簇索引叶⼦节点存储的是主键 id,因此当非聚簇索引能够匹配上之后,只能拿到主键信息,需要使⽤主键 id 再去聚簇索引中获取表的相关信息,所以执⾏效率没有聚簇索引⾼,⽽这个查询的过程就叫做回表查询。
回表查询——> 二级索引——>ID——>又去查询聚簇索引,找到对应的数据。
总结:
聚簇索引和⾮聚簇索引的区别主要体现在两⽅⾯:
1.执⾏效率:聚簇索引查询速度更快,因为聚簇索引存储的是数据,⽽⾮聚簇索引存储的是主键 ID,需要进⾏回表查询。
2. 数量上:聚簇索引⼀个表只能有⼀个,⽽⾮聚簇索引可以有多个。
三、索引校验:确认创建的索引是否生效
explain语句可以分析sql的执行逻辑,顺序,是否使用索引等等。
四、建表的时候创建索引:
五、索引失效场景
1、联合索引不满足最左匹配原则(也叫前缀匹配)
1.1 A+B+C:满足最左匹配原则,可以使用联合索引
1.2 A+B:满足最左匹配原则,可以使用联合索引
1.3 A+C:符合最左匹配原则,可以触发联合索引
1.4 A:符合最左匹配原则,可以触发联合索引
1.5 B+A:符合最左匹配原则,可以触发联合索引
1.6 C+A:符合最左匹配原则,可以触发联合索引
1.7 A+C+B:符合最左匹配原则,可以触发联合索引
1.8 C+A+B:符合最左匹配原则,可以触发联合索引
1.9 B+C+A:符合最左匹配原则,可以触发联合索引
1.10 B+C:不符合最左匹配原则,不能使用联合索引
1.11 B 或 C:不符合最左匹配原则,不能使用联合索引
1.12 C+B:不符合最左匹配原则,不能使用联合索引
总结: 即有A(最左侧的)字段就可以使用联合查询。
值得注意的是,当遇到范围查询(>、<、between、like)就会停止匹配。
select * from t where a=1 and b>1 and c =1;
这样a,b可以用到(a,b,c),c索引用不到这条语句只有 a,b 会用到索引,c 都不能用到索引。但是如果是建立(a,c,b)联合索引,则a,b,c都可以使用索引,因为优化器会自动改写为最优查询语句。
select * from t where a=1 and b >1 and c=1;
如果是建立(a,c,b)联合索引,则a,b,c都可以使用索引。优化器改写为
select * from t where a=1 and c=1 and b >1;
这也是最左前缀原理的一部分,索引index1:(a,b,c),只会走a、a,b、a,b,c 三种类型的查询,其实这里说的有一点问题,a,c也走,但是只走a字段索引,不会走c字段。
另外还有一个特殊情况,
select * from table where a = '1' and b > ‘2’ and c='3';
这种类型的也只会有 a与b 走索引,c不会走。
像select * from table where a = ‘1’ and b > ‘2’ and c=‘3’ 这种类型的sql语句,在a、b走完索引后,c肯定是无序了,所以c就没法走索引,数据库会觉得还不如全表扫描c字段来的快。
以index (a,b,c)为例建立这样的索引相当于建立了索引a、ab、abc三个索引。一个索引顶三个索引当然是好事,毕竟每多一个索引,都会增加写操作的开销和磁盘空间的开销。
2、使用错误的模糊查询