索引能够帮助你做什么
一个索引最多能做三个事情:
- 过滤(filter)
- 排序或分组(sort/group)
- 覆盖(cover)
对覆盖的解释
一个基本查询的工作流:
- 用索引去查找匹配的记录并获取指向该数据的指针
- 利用指向相应数据的指针
- 返回记录
当覆盖索引被用到时,索引已经覆盖了所有查询中的域,所以上述过程中的step#2可以被跳过,现在这个工作流是这样的: 1.用索引去找相匹配的记录 2.返回记录
单列等值查询
这是最常见的场景:
SELECT * FROM t WHERE c = 100
- 这种情况当然是给表加上
c的索引 - 需要注意的是如果添加的索引不够有选择性(selective),优化器可能会做全表扫描来做优化
第二种场景:
SELECT c1, c2 FROM t WHERE c = 100 - 这种情况考虑给表加上(c,c1,c2)的索引,因为这会成为一个覆盖索引
- 注意别创建一个(c1,c2,c),它不会对过滤有用。
多等值查询
常见情况:
SELECT * FROM t WHERE c = 100 and d = 'xyz'
- 加上(c,d) 或 (d,c)的索引
- 注意不要单独添加c和d两个索引
等值和非等值查询组合
场景:
SELECT * FROM t WHERE c > 100 and d = 'xyz'
- 当我们用一个非等值列时,会妨碍我们用其他的索引中的列。
- 故我们创建(d,c)的索引,我们就能够同时在c和d上过滤。
多非等值查询
场景:
SELECT * FROM t WHERE c > 100 and b < 10 and d = 'xyz'
- 当有两个或两个以上的非等值查询时,我们知道其中有一列一定不能应用到过滤中,故需要做一个抉择:(d,b)还是(d,c)?
- 根据表中数据来定夺:一定要选择区分度高的索引列
多等值查询和排序
场景:
SELECT * FROM t WHERE c = 100 and d = 'xyz' ORDER BY b
- 索引挑选规则是过滤优先,之后才是排序
- 故我们挑选(c,d,b)或(d,c,b)
- 若Sql语句为:
SELECT c1, c2 FROM t WHERE c = 100 and d = 'xyz' ORDER BY b,那么选择(c,d,b,c1,c2)是最有效率的索引。
非等值查询和排序
场景一:
SELECT * FROM t WHERE c > 100 and d = 'xyz' ORDER BY b
- 有两种选择:1.在d上过滤并在b上排序 2. 在d和c上过滤 两种方案需要根据实际的数据来抉择
场景二:
SELECT * FROM t WHERE c > 100 ORDER BY b - 这种情况大多数情况会选择非等值索引,也就是c