MySQL 执行慢原因分析

SQL执行慢不外乎以下原因:
1、查询语句设计不合理。简单的 SQL 语句执行效率高,复杂的 SQL 语句执行效率低。
2、索引处理不当,如忘记在 WHERE 后面加上索引,导致查询过程中无法使用索引来特别优化查询。
3、表没有做合理的分区。

在实践过程中,我们可以根据多变的情况进行逐步分析:

情况分析

在生产环境中,相同数据量情况下,有SQL偶尔执行慢即出现频率低,也有SQL每次执行都慢即出现频率高。

出现频率低情景

1、InnoDB脏页刷新
Innodb为了优化写效率,采用了内存缓冲及redo log(写磁盘)的方式,当内存页与磁盘页数据不一致时(脏页),mysql会进行刷盘(定时批量)。或者mysql dump之后,从redo log恢复最新数据。
redo log是有容量的,如果数据库操作频繁,redo log会写满,那么需要写到磁盘,而不能等到空闲的时候做刷盘了,这个时候必须停止其他操作,因此正在执行的操作就会执行得慢。

2、操作等待锁资源
当我们在update数据时,需要获取行锁,行锁为悲观锁。当行锁被其他事务获取时,当前事务需要等待,直到行锁被释放。

出现频率高情景

  • SQL执行没有走索引
    1、SQL执行时的where没有使用索引,进行全表查询,当数据量大时,执行效率低
    2、SQL执行时where里使用了索引,那么通过explain进行分析
    如果where条件中对索引字段进行运算操作或者函数操作,SQL执行时不会触发索引执行。

  • SQL的执行走索引
    1、通过explain分析,虽然走了索引,但类型为all,表明依然走的是全表查询
    场景有:
    使用了前缀模糊匹配 like,不能命中索引
    = 前的索引列上进行了表达式运算
    数据表中 phone 字段是字符串类型,而查询时使用了数字类型,会触发隐式类型转换,不会命中索引

2、根据索引查找的机制进行分析,从辅助索引查找到数据主键时,在通过聚簇索引找到行数据,如果索引不能有效的区分数据,比如像年龄,不能区分大部分数据时(年龄分布平均)
mysql会根据这个预测分析通过全表查询(遍历行数据)会比通过索引效率高(先通过辅助索引,再通过聚簇索引分析行数据)

3、单表数据量超过千万后,性能会出现下降(b+tree数据结构缺点)

猜你喜欢

转载自blog.csdn.net/BBinChina/article/details/124489238
今日推荐