好的索引,你值得拥有

其实好的索引的原则,很简单,只要满足三个条件:

  1. 能够覆盖查询语句
  2. 能够避免排序
  3. 窄索引片

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条不能兼得;
现有数据库索引已经设计好,投入使用,但是效率低,是不是直接添加一个最佳索引就行?
添加索引的成本?
跨表查询的情况?等等