查询优化

mysql查询要经过客户端传输、服务器解析、生成执行计划、执行、返回给客户端等步骤

优化数据访问

是否向数据库请求了不必要的数据查询不需要的记录

多表关联返回全部列

总是取出全部列(select * from)

重复查询相同数据

mysql是否在扫描额外的记录响应时间

扫描的行数

访问类型

全表扫描 > 索引扫描 > 范围扫描 > 唯一索引扫描 > 常数引用

重构查询的方式一个复杂查询 or 多个简单查询

切分查询

分解关了查询

查询执行的基础

查询执行路径

查询状态Sleep

Query
Locked
Analyzing and statistics
Coping to tmp table [on disk]
Sorting result
Sending data

关联查询

假设有查询语句:

SELECT tbl1.col1, tbl2.col2 FROM tbl1 INNER JOIN tbl2 USING(col3) WHERE tbl1.col1 IN(5,6);

则查询关联的顺序如图中所示:

tips:如果对某个查询执行explain extended,再执行show warnings,就可以看到mysql重构后的完整查询。

msyql做关联查询时会做关联表优化,使用straight_join关键字可以禁止关联顺序优化,这在某些特殊场合是有效的。

排序优化

应该尽量避免排序,如果一定需要排序,优先使用索引排序,若不能使用索引;尽量使用order by字段的表作为驱动表。这样可以在处理第一张表的时候就进行文档排序,避免生成临时表。

索引合并优化松散索引扫描

最大值和最小值优化

优化limit分页

优化分页查询最简单的办法就是尽可能地使用索引覆盖扫描,然后根据需要再做一次关联返回需要的列;而不是直接查询所有的列。下面我们看一个例子:

表结构

假设有一张表film,结构如下:

执行计划

优化前

例如我们常用的分页查询,执行时间是0.03s,使用explan命令可以看到执行计划中rows为1000,而且Extra列有using filesort,如果数据量更大,sql可能会更慢

优化后

那么如果我们换一种关联查询的方式,title字段order by使用了覆盖索引扫描,即不用再做文档排序,这种方式对于大表的排序是非常有效的。整个查询时间小于0.01s,通过explain可以看到执行计划中驱动表的Extra列为using index,则即意味着我们在这个查询使用到了覆盖索引,这里有几点需要说明:film表的主键是film_id,而title列是二级索引,所以在第一次查询的film_id和description使得无法使用title字段做覆盖索引扫描

如果我们先扫描一次film表通过title索引覆盖扫描film_id,然后通过临时表关联主表通过primary key查出需要的列