好的索引,你值得拥有
其实好的索引的原则,很简单,只要满足三个条件:
- 能够覆盖查询语句
- 能够避免排序
- 窄索引片
1. 能够覆盖查询语句
举个例子: select a,c,d from table1 where b = 1 and e = 2 and g > 7;
能够覆盖查询语句,即意味着索引要含:a,b,c,d,e,g
为什么呢,因为如此一来,所有的查询结果,都在索引里能找到,不需要到表数据里再查找。
2. 能够避免排序
举个例子: select a,c,d from table1 where b = 1 and e = 2 and g > 7 order by g desc;
如果按照a,b,c,d,e,g的顺序建立索引,那么意味着该索引是按照a来排序的,所以在索引过滤完,还需要根据g进行二次排序
那如何才能做到根据g来排序?
很简单:索引的顺序调整一下
b, e, g, a, c, d
假设索引的实际内容如下:
1, 2, 8, x, x, x
1, 2, 9, x, x, x
1, 2,10, x, x, x
因为b=1,e=2是固定的,所以只要把g提到前面,那么排序必然是按照g来的
如此一来,根据a, b, g过滤好的索引,天然就是排序好的结果
3.窄索引片
什么是索引片,以及什么样的索引片是窄索引片,已经在索引这篇中介绍过了
所谓的索引片,就是优化器根据查询语句,在索引中,实际使用的用于检索的索引
举个例子:select a,c,d from table1 where b = 1 and e = 2 and g > 7 and c < 5 order by g desc;
根据优化器的逻辑:
如果索引是(a,b,c,d,e,g) 那么索引片是0,即没有索引片,因为a,在查询语句中根本就没有查询条件
那么好的索引是什么样的:
b, e, g, a, c, d
让我们来看看这个索引,
当扫描b时,b=1, 加入到索引片中(b);
当扫描e时,e=2, 加入到索引片中(b,e);
当扫描g时,g >7,加入到索引片中(b,e,g),但是因为g是范围查询,索引g之后的条件,都不能纳入到索引片中
所以最终索引片是(b, e, g) 即用b, e, g来在索引的B树中找到索引们
那么c < 5,如果c在索引中,c < 5 就是过滤列,在索引过滤的基础上,再进行对索引过滤。
所以,对于select a,c,d from table1 where b = 1 and e = 2 and g > 7 order by g desc;
最佳的索引是什么:
b, e, g, a, c, d
满足了1, 2,3条,优化器只要对索引进行查找即可,就能过滤出所要的数据!
那么索引设计就是这么简单吗?
当然不是,以上只是理想情况下,还有比如:
2,3条不能兼得;
现有数据库索引已经设计好,投入使用,但是效率低,是不是直接添加一个最佳索引就行?
添加索引的成本?
跨表查询的情况?等等