mysql索引优化

134 阅读3分钟

mysql优化工具:

  1. 索引优化使用explain查看执行计划;
  2. 使用trace工具可以查看成本扫描;

优化原则:

  1. 查询的字段尽量被索引覆盖
  2. 遵循最左前缀原则:使用联合索引查询要从最左前列开始,不跳过索引中的列。
  3. 不要在索引列上做任何操作,例如,函数,手动/自动类型转换。
  4. 联合索引的范围查找右边的列不走索引
  5. 尽量使用覆盖索引,减少select*语句
  6. !=无法使用索引
  7. is null,is not null一般情况下也无法使用索引,因为null在索引树中,会集中在左端/右端存储。
  8. like后模糊匹配走索引
  9. 字符串不加单引号会导致类型转换,导致索引失效
  10. in or,会根据检索比例,表大小等因素评估是否使用索引; 表小不走索引; in条数过多,不走索引。
  11. 范围太小/太大,会导致索引失效 太小/太小都会扫全表,避免回表,所以将范围控制在合适的范围内,或使用覆盖索引优化。

索引下推

Mysql在5.6开始,引入索引下推,like后模糊匹配索引不会断,会进行后续索引列的过滤之后,再进行回表。

  1. 联合索引第1个字段使用范围查找,一定不会走索引
  2. 确定更有方案可以强制走索引
  3. 可以使用覆盖索引优化
  4. in or表小不走索引; in条数过多,不走索引。
  5. like后模糊匹配,通常情况下走索引

但是如果匹配后查询的结果集大于某个阈值,且还要回表,则不会走索引。

orderby,groupby优化

  1. where和orderby组合要符合最左前缀原则
  2. 尽量使用where将范围缩小,优先where优化
  3. 使用覆盖索引优化
  4. order by x desc需要在创建索引时声明
  5. 能使用where解决的,就不要用having
  6. group by优化原理同order by
  7. group by会先排序,后分组,为避免显式/隐式排序,可以使用order by null禁止排序。

索引设计原则

  1. 代码先行,索引后上
  2. 尽量使用2个左右的联合索引,覆盖大多数业务场景
  3. 不要在小基数上建立索引
  4. 长字符串可以采用前缀索引
  5. where和order by冲突时,优先where
  6. 可以开启慢sql日志,针对慢sql进行优化

分页优化

  1. mysql会将前面的行都扫描出来,再扫描继续扫描需要的行数
    所以可以使用id>start直接定位,前提是连续自增,使用条件比较苛刻
  2. 使用where条件检索出id,然后in(ids)查询

表连接优化

  1. 小表驱动大表,索引字段建立索引
  2. 连接字段有索引,使用嵌套连接查询,将驱动表查询结果集拿到内存bufferpool,拿出1行,去用索引定位被驱动表匹配的数据,然后拿出第2行,直到结果集匹配完;
    连接字段无索引,使用基于块的嵌套连接查询,将驱动表的数据缓存到joinbuffer,然后逐行拿出被驱动表的数据到内存匹配;
    驱动表的数据在1个joinbuffer存不下,会进行分段存储。

in和exists优化

  1. in先里后外,exists先外后里
    保证先查询的是小表。

count优化

  1. mysql5.7之后,字段没有索引,count(*)=count(1)=count(0)>count(id)>count(字段)
    字段有索引,count(*)=count(1)=count(0)>count(字段)>count(id)
  2. count(字段/id),会遍历普通索引树/主键索引树,取出字段/id,判空,逐行累加
    count(*),count(1),count(0),遍历整表,不数据,不判空,逐行累加。
  3. myisam不支持事务,不加条件可以直接返回总行数;
    innodb因为有mvcc机制,不同事务看到的行数可能不同,所以需要实时累计。