扫描额外的记录
在确定了只返回需要的数据以后,接下来看看查询为了结果是否扫描了过多的数据。我们有以下几个指标判断:
- 响应时间
- 扫描的行数
- 返回的行数
这三个指标都会记录到慢日志中,所以检查慢日志记录是找出扫描行数过多的查询的好办法。
响应时间
响应时间是两个部分之和:服务时间和排队时间
- 服务时间是指数据库处理这个查询真正花的时间
- 排队时间是指服务器因为等待某些资源而没有真正执行查询的时间。可能是等I/O操作完成,也可能是等待行锁,等等。
扫描的行数和返回的行数
对于上面的响应时间的不准确性,所以比较常用的一种分析查询的效率的方式就是通过查看扫描的行数和返回的行数,理想情况下,扫描与返回的行数应该是一致的。但是在关联查询时,这两者的行数之间是会有差的。
通常我们会使用EXPLAIN语句来分析查询语句涉及到的行数。一般MySQL能够使用如下三种方式应用Where条件,从好到坏依次为:
- 在索引中使用Where条件来过滤不匹配的记录,这是在存储引擎层完成的。
- 使用索引覆盖扫描(在Extra列中出现了Using index)来返回记录,直接从索引中过滤不需要的记录并返回命中的结果。这是在MySQL服务层完成的,但无须再回表查询记录。
- 从数据表中返回数据,然后过滤不满足条件的记录(在Extra列中出现Using Where)。这在MySQL服务器层完成,MySQL需要先从数据表独处记录然后过滤。
如果发现查询需要扫描大量的数据但只返回少数的行,通常尝试下面的技巧去优化它:
- 使用索引覆盖扫描,把所有需要用的列都放到索引中,这样存储无须回表获取对应行就可以返回结果了
- 改变表结构。例如使用单独的汇总表
- 重写这个复杂的查询,让MySQL优化器能够以更优化的方式执行这个查询。