MySQL索引优化

MySQL日常查询使用中,经常遇到索引失效等情况导致查询效率低, 下面总结了一些SQL优化的方法。

SQL优化方法

  1. 不建议使用%前缀模糊查询

  2. 避免在WHERE子句中对字段进行函数或表达式操作

  3. 对于联合索引来说,要遵守最左前缀法则

  4. SQL语句中IN包含的值不应过多
    连续的数值场景建议用范围区间

  5. 禁止使用SELECT * 查询所有字段,仅查询需要的字段。
    全字段查询不能用到覆盖索引,会降低SQL执行效率;而且查询过多不需要的字段数据,也将消耗更多的IO

  6. 当只需要一条数据的时候,使用limit 1
    使EXPLAIN中type列达到const类型

  7. 如果排序字段没有用到索引,就尽量少排序。 排序字段加入联合索引, 可以避免在文件排序Using filesort。

  8. 注意范围查询语句
    联合索引的最左匹配原则,在遇到范围查询(如 >、<)的时候,就会停止匹配,也就是范围查询的字段可以用到联合索引,但是在范围查询字段的后面的字段无法用到联合索引。注意,对于 >=、<=、BETWEEN、like 前缀匹配的范围查询,并不会停止匹配。

  9. WHERE 子句中的 OR
    如果在 OR 前的条件列是索引列

    • OR 后面的条件列不是索引列,那么索引会失效
    • OR 后面的条件是索引列, 那么type = index merge,意思就是对idx1 和 idx2 分别进行了扫描,然后将这两个结果集进行了合并,这样做的好处就是避免了全表扫描。
  10. 对索引隐式类型转换
    MySQL 数据类型转换规则是会将字符串转成数字处理。

    • 如果索引字段是字符串类型,但是在条件查询中,输入的参数是整型的话,那么这条语句会走全表扫描。
    • 如果索引字段是整型类型,但是在条件查询中,输入的参数是字符串的话,那么这条语句会走索引。
  11. JOIN优化

    • LEFT JOIN A表为驱动表
    • INNER JOIN MySQL会自动找出那个数据少的表作用驱动表- RIGHT JOIN B表为驱动表
  12. 尽量用UNION ALL代替UNION
    UNION 和UNION ALL的区别是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。

  13. 区分IN和EXISTS

    • EXISTS,外层表为驱动表
    • IN,子表为驱动表
      IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况
  14. 合理的分页方式以提高分页的效率
    使用游标方式, 例如id > maxId limit 100;

  15. 必要时可以使用force index来强制查询走某个索引

  16. 关于select count
    在MySQL 5.7.18之前,InnoDB通过扫描聚集索引处理SELECT COUNT(*)语句。从MySQL 5.7.18开始,InnoDB通过遍历最小的可用二级索引来处理SELECT COUNT(*)语句,除非索引或优化器明确指示使用不同的索引。如果不存在二级索引,则扫描聚集索引。这样的设计单从 IO 的角度就节省了很多开销。
    InnoDB以同样的方式处理SELECT COUNT(*)和SELECT COUNT(1)操作,没有性能差异。 因此,建议使用符合SQL标准的count(*)。
    count(*)=count(1)>count(primary key)>count(非主键column)。

  17. 主键索引最好是自增的。 使用非自增主键,由于每次插入主键的索引值都是随机的,会导致页分裂, 造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率

  18. 索引区分度

建立联合索引时的字段顺序,对索引效率也有很大影响。越靠前的字段被用于索引过滤的概率越高,实际开发工作中**建立联合索引时,要把区分度大的字段排在前面,这样区分度大的字段越有可能被更多的 SQL 使用到**。
  1. 索引下推优化(index condition pushdown), 可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

慢SQL排查方法 Explain

type

常见的类型有: ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好

  • ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
  • index: Full Index Scan,index与ALL区别为index类型只遍历索引树
  • range:范围扫描,是一个有限制的索引扫描,开始于索引的某一点,返回匹配这个值域的行。比全索引扫描好一些,因为用不着遍历全部索引。显而易见的范围扫描是带有between或在where子句里带有>的查询。
  • ref: 是一种索引访问,返回所有匹配某个单个值的行。然而,它可能会找到多个符合条件的行,此类索引访问只有当使用非唯一性索引或者唯一性索引的非唯一性前缀时才会发生。
  • eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
  • const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下。
  • NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

possible_keys

指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用

Key

key列显示MySQL实际决定使用的键(索引)

如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

rows

表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

Extra

该列包含MySQL解决查询的详细信息,有以下几种情况:

  • Using index表示MySQL将使用覆盖索引,以避免回表查询
  • Using index condition :出现这个说明mysql使用了覆盖索引,避免访问了表的数据行,效率不错
  • Using where:表示 MySQL 服务器从存储引擎收到查询数据,再进行“后过滤”(Post-filter)。所谓“后过滤”,就是先读取整行数据,再检查此行是否符合 where 句的条件,符合就留下,不符合便丢弃。因为检查是在读取行后才进行的,所以称为“后过滤”。 建议添加适当的索引
  • Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询, 通常是因为GROUP BY的列没有索引,或者GROUP BY和ORDER BY的列不一样,也需要创建临时表,建议添加适当的索引
  • Using filesort:MySQL对数据不是按照表内的索引顺序进行读取,而是使用了其他字段重新排序,建议添加适当的索引
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值