开发人员不得不知的MySQL索引和查询优化

作者:微信小助手

发布时间:2019-03-18T18:20:33

本文主要总结了工作中一些常用的操作及不合理的操作,在对慢查询进行优化时收集的一些有用的资料和信息,本文适合有 MySQL 基础的开发人员。


索引相关


索引基数


基数是数据列所包含的不同值的数量,例如,某个数据列包含值 1、3、7、4、7、3,那么它的基数就是 4。


索引的基数相对于数据表行数较高(也就是说,列中包含很多不同的值,重复的值很少)的时候,它的工作效果最好。


如果某数据列含有很多不同的年龄,索引会很快地分辨数据行;如果某个数据列用于记录性别(只有“M”和“F”两种值),那么索引的用处就不大;如果值出现的几率几乎相等,那么无论搜索哪个值都可能得到一半的数据行。


在这些情况下,最好根本不要使用索引,因为查询优化器发现某个值出现在表的数据行中的百分比很高的时候,它一般会忽略索引,进行全表扫描。惯用的百分比界线是“30%”。


索引失效原因


索引失效的原因有如下几点:

  • 对索引列运算,运算包括(+、-、*、/、!、<>、%、like'%_'(% 放在前面)。

  • 类型错误,如字段类型为 varchar,where 条件用 number。

  • 对索引应用内部函数,这种情况下应该要建立基于函数的索引。例如 select * from template t where ROUND (t.logicdb_id) = 1,此时应该建 ROUND (t.logicdb_id) 为索引。

    MySQL 8.0 开始支持函数索引,5.7 可以通过虚拟列的方式来支持,之前只能新建一个 ROUND (t.logicdb_id) 列然后去维护。

  • 如果条件有 or,即使其中有条件带索引也不会使用(这也是为什么建议少使用 or 的原因),如果想使用 or,又想索引有效,只能将 or 条件中的每个列加上索引。

  • 如果列类型是字符串,那一定要在条件中数据使用引号,否则不使用索引。

  • B-tree 索引 is null 不会走,is not null 会走,位图索引 is null,is not null 都会走。

  • 组合索引遵循最左原则。


索引的建立


索引的建立需要注意以下几点:

  • 最重要的肯定是根据业务经常查询的语句。

  • 尽量选择区分度高的列作为索引,区分度的公式是 COUNT(DISTINCT col) / COUNT(*),表示字段不重复的比率,比率越大我们扫描的记录数就越少。

  • 如果业务中唯一特性最好建立唯一键,一方面可以保证数据的正确性,另一方面索引的效率能大大提高。


EXPLIAN 中有用的信息


基本用法


EXPLIAN 基本用法如下:

  • desc 或者 explain 加上你的 SQL。

  • extended explain 加上你的 SQL,然后通过 show warnings 可以查看实际执行的语句,这一点也是非常有用的,很多时候不同的写法经 SQL 分析后,实际执行的代码是一样的。


提高性能的特性


EXPLIAN 提高性能的特性如下:

  • 索引覆盖(covering index):需要查询的数据在索引上都可以查到不需要回表 EXTRA 列显示 using index。