Whoosy's Blog

藏巧于拙 用晦而明 寓清于浊 以屈为伸

0%

Mysql优化的思路

编码不易,转载请注意出处!

大原则:如果mysql优化器计算使用索引比全表扫描还慢,则不会使用索引,此原因会导致很多条件不走索引。

Mysql数据库优化的主要思路集中在3个方面

  • sql语句优化
  • 索引设计优化
  • 数据库结构优化

1.sql语句优化

  • 1)应尽量避免在 where 子句中使用!= 、<>、not in 、not exists、not like等反向操作符,否则将引擎放弃使用索引而进行全表扫描,通常情况下这些负向操作可以优化为in查看从而正常走索引查询。
  • 2)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0。
  • 3)很多时候用 exists 代替 in 是一个好的选择。
  • 4)用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤,而where语句可以针对索引树做查询。
  • 5)索引字段不要做函数操作,会破坏b+ tree的有序性,优化器会放弃走索引。
  • 6)基于最左前缀匹配原则,按照索引定义的字段顺序写sql。
  • 7)建议只查需要的字段,比如覆盖索引可以有效避免回表,尽量不要使用 select *。
  • 8)如果explain执行计划中没有走索引或不是最优的,可以用force index强制走某个索引。
  • 9)如果使用的mysql版本支持开启索引条件下推,尽量开启它,因为它可以在使用联合索引时避免回表查询。

2.索引设计优化

  • 1)在经常用在连接的列上建立索引,这些列主要是一些外键,可以加快连接的速度。
  • 2)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排好序了,其指定的范围是连续的。
  • 3)对于那些在查询中很少使用的列不应该为其单独创建索引。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。实在想建立的话考虑一下能不能和其他字段建立联合索引。
  • 4)对于一些区分度不是很好的列尽量不要建立索引,比如性别。因为在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
  • 5)对于一些可以在业务里面就可以生成唯一性的字段,不要对其建立唯一索引,因为唯一索引插入或者更新的时候不能利用到change_buffer,总要去读盘检查唯一性,效率很低。
  • 6)如果某个列字符串特别长,可以考虑使用前缀索引,但要注意找到合适的前缀索引长度,否则会适得其反,比如邮件 @后面可能都一样,比较适合用前缀索引。
  • 7)对于一些字符串前缀区分度不好的列时,建议使用倒序索引,目的是增加区分度,比如身份证号,前面区分度不大,但是不支持范围查询。

3.数据库结构优化

  • 范式优化: 比如消除冗余(节省空间。。)
  • 反范式优化:比如适当加冗余等(减少join),是否加冗余还是要看具体场景
  • 水平、垂直分库分表。