编码不易,转载请注意出处!
大原则:如果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),是否加冗余还是要看具体场景
- 水平、垂直分库分表。