三星索引详解

什么是三星索引

★☆☆
定义:如果与一个查询相关的索引行是相邻的,或者至少相距足够靠近的话,那这个索引就可以标记上一颗星。
收益:它最小化了必须扫描的索引片的宽度。
实现:把 WHERE 后的等值条件列作为索引最开头的列,如此,必须扫描的索引片宽度就会缩至最短。
★★☆

定义:如果索引行的顺序与查询语句的需求一致,则索引可以标记上第二颗星。
收益:它排除了排序操作。
实现:将 ORDER BY 列加入到索引中,保持列的顺序
★★★
定义:如果索引行中包含查询语句中的所有列,那么这个索引就可以标记上第三颗星。
收益:这避免了访问表的操作(避免了回表操作),只访问索引就可以满足了。
实现:将查询语句中剩余的列都加入到索引中。

如果某个列经常更新,最好放在复合索引中后面的位置,以减小维护索引的代价

实例:

select A,B,C,D from user where A="xx" and B = "xx" order by C;

比如A的选择性为 0.01%
B的选择性为 0.1%
最佳的索引是建复合索引 (A, B, C, D) ,这是一个三星索引。

★:
过滤尽可能多的行,这意味着把选择性高的索引放在前面A、B。
减少索引片的大小以减少需要扫描的数据行

★★:
也就是说,当经过了A,B的筛选之后,筛选出来的行本身就是已排序的C。
避免排序,减少磁盘 IO 和内存的使用;

★★★:
通过宽索引实现索引覆盖。
避免每一个索引对应的数据行都需要进行一次随机 IO 从聚集索引中读取剩余的数据;

为什么有时候无法同时获得第一、二颗星?

在实际场景中,问题往往没有这么简单,我们虽然可以总能够通过宽索引避免大量的随机访问,但是在一些复杂的查询中我们无法同时获得第一颗星和第二颗星。

SELECT id, name, age FROM students
WHERE age BETWEEN 18 AND 22
  AND city = "Wuhan"
ORDER BY name;

在上述查询中,我们总可以通过增加索引中的列,字段全覆盖的方法来获得第三颗星,但是如果我们想要获得第一颗星就需要最小化索引片的大小,这时索引的前缀必须为 (city, age),在这时再想获得第三颗星就不可能了,哪怕在 age 的后面添加索引列 name,也会因为 name 在范围索引列 age 后面必须进行一次排序操作,最终得到的索引就是 (city, age, name, id)

如果我们需要在内存中避免排序的话,就需要交换 age 和 name 的位置了,在这时就可以得到索引 (city, name, age, id),当一个 SQL 查询中同时拥有范围谓词和 ORDER BY 时,无论如何我们都是没有办法获得一个三星索引的,我们能够做的就是在这两者之间做出选择,是牺牲第一颗星还是第二颗星。

实际上大多数时候,我们更偏爱第一颗星。我们希望减少需要扫描的数据行。


版权声明:本文为qq_44073614原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>