慢查询总结


总结一下出现慢查询的原因,参考《高性能Mysql》

原因

慢查询的具体原因很多,但是最基本的原因就是查询访问的数据太多,其中包括检索了过多的列和过多的行,或者mysql服务器层分析了大量不需要的数据

请求了不需要的数据

  1. 查询了不需要的记录
    这里书中举例的场景是搜索大量数据,然后取出前面的N行,而不是从sql中直接limit,这个问题一般不会犯。
  2. 多表关联时返回全部列 && 总是取出全部列
    这两个场景类似,也就是说不要select * ,取出自己需要的列就可以了。
  3. 查询重复的数据
    一般是说业务中没有加缓存,重复执行相同的语句,返回相同的数据,这一点不是再说慢查询,是从数据库性能出发的。

Mysql是否扫描了额外的记录

这部分有三个指标

  • 响应时间
  • 扫描的行数
  • 返回的行数
    其中响应时间是指mysql执行sql的时间和等待资源(io和行锁)的时间。
    理想情况下,扫描的行数应该和返回的行数相同,但是一般很难做到。这部分的解决方案就是加合适的索引。
    对于一般的where条件,我们从执行计划可以看到,最好的是在索引中直接使用where条件过滤,其次是使用覆盖索引,不需要回表查询数据(using index),直接返回命中结果,最后就是从数据表中返回数据,然后过滤不满足条件的记录。
这里额外说一下Mysql的服务器层和引擎层

首先是服务层,服务层是向上对外提供查询能力,向下调用引擎读写数据。首先是连接器,接收客户端请求,建立连接,然后是查询缓存,是语句和结果的kv缓存,如果命中直接返回,接着是分析器,会对语句进行词法分析和语法分析,例如查询不存在的列就是这个阶段报错,接着是优化器,决定使用哪个引擎,或者join表的顺序,接下来就是执行器,根据语句调用引擎读写。
引擎层就是具体的innoDb这样的提供读写接口的引擎。

解决

  1. 拆分复杂查询为多个简单查询,
  2. 切分查询,一次性执行一个大的sql(删除大量数据),会锁住很多数据,耗尽系统资源,阻塞小sql,所以可以拆分,多次执行。
  3. 分解关联查询,在工程中,一般都不会使用join,都是在应用层代码中完成聚合逻辑,一个是使得缓存的命中变高,因为聚合多表查询条件,查询组合就会变得很多,缓存命中率就会下降,同时在应用层更容易扩展且容易复用,对于引擎层,多个小的查询也可以降低锁粒度

  目录