Indexing 101: Optimizing MySQL queries on a single table 笔记

191 阅读2分钟

索引能够帮助你做什么

一个索引最多能做三个事情:

  • 过滤(filter)
  • 排序或分组(sort/group)
  • 覆盖(cover)

对覆盖的解释

一个基本查询的工作流:

  1. 用索引去查找匹配的记录并获取指向该数据的指针
  2. 利用指向相应数据的指针
  3. 返回记录

当覆盖索引被用到时,索引已经覆盖了所有查询中的域,所以上述过程中的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