众所周知,MySQL联合索引遵循最左前缀匹配原则,少数情况不会遵循(如果有兴趣可以看看)文章)。创建联合索引时,建议先将区分度高的字段放在第一列。至于如何统计判别率,可以按照下面的方法进行。创建测试表进行测试:CREATETABLE`test`(`id`intNOTNULLAUTO_INCREMENTCOMMENT'primarykey',`a`intNOTNULL,`b`intNOTNULL,`c`intNOTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBCOMMENT='测试表';统计每个字段的区分度:selectcount(distincta)/count(*),count(distinctb)/count(*),count(distinctc)/count(*)fromtest;值越大,区分度越高,排在第一列最前面。很多人不知道联合索引在B+树中是怎么存储的?我简单画一下。例如在(a,b)字段上创建联合索引,存储结构类似如下:叶子节点存储所有数据,通过顺序指针连接,数据先按字段a排序,再按字段排序b当字段a的值相等时。a字段的值是全局排序的,分别有1,1,1,2,2,2。b字段的值是全局无序的,分别为1、3、5、1、3、5,只有a字段的值相等时才能表现出局部有序。所以在执行SQL查询时,如果where条件中没有a字段,只有b字段,则无法使用索引,如下:select*fromtestwhereb=1;有文章说,在(a,b)两个字段上创建联合索引,会创建两个索引,分别是(a)和(a,b)。这实际上是一个不恰当的表述,尽管结果是正确的。来做几道关于联合指数的经典面试题,试试看你都掌握了什么?问题一:如何为下面的SQL创建联合索引?SELECT*FROMtestWHEREa=1andb=1andc=1;你以为的答案是(a,b,c),其实答案是6,三个abc的排列组合,(a,b,c),(a,c,b),(b,a,c),(b,c,a),(c,a,b),(c,b,a)。MySQL优化器调整条件的顺序以适合索引。给面试官补充一下,区分度高的字段放在前面,大大加分。问题二:如何为下面的SQL创建联合索引?SELECT*FROMtestWHEREa=1andb>1andc=1;考察的知识点是:联合索引遇到范围匹配就停止,不再匹配后面的索引字段。所以答案应该是:(a,c,b)和(c,a,b)。创建(a,c,b)和(c,a,b)索引时,查询会使用3个字段的索引,效率更高。如何判断使用了3个字段的索引,而不是只使用前两个字段的索引?有一种非常简单的方法可以查看执行计划的索引长度。由于int类型的字段占4个字节,所以3个字段的长度恰好是12个字节。问题三:如何为下面的SQL创建联合索引?SELECT*FROMtestWHEREain(1,2,3)andb>1;答案是(a,b)。in条件查询会转化为等价查询,验证一下:可以看到使用了两个字段的索引。所以我们平时做开发,想办法把rangequery转成inconditionalquery,效率更高。文章持续更新中,微信搜索“一光架构”阅读更多技术干货第一时间。
