为什么以上示例中显示的是“Using index condition”而不是“Using where”呢?这是MySQL Version 5.6+ 的新功能特性,Index Condition Pushdown (ICP)。简单的说就是减少了查询执行时MySQL服务和下层数据引擎的交互次数,达到提高执行性能的目的。如果您关闭MySQL服务中的ICP功能(这个功能默认打开),以上示例的第二个执行语句就会显示“Using where”了。
Using temporary:Mysql中的数据引擎需要建立临时表进行中间结果的记录,才能完成查询操作。这个常见于查询语句中存在GROUP BY 或者 ORDER BY操作的情况。但并不是说主要子查询中出现了GROUP BY 或者 ORDER BY就会建立临时表,而如果Group By 或者 Order By所依据的字段(或多个字段)没有建立索引,则一定会出现“Using temporary”这样的提示。另一种常见情况发生在子查询join连接时,连接所依据的一个字段(或多个字段)没有建立物理外键和索引。一旦在Extra字段中出现了“Using temporary”提示,一般来说这条子查询就需要重点优化。
Using filesort:Mysql服务无法直接使用索引完成排序时,就需要动用一个内存空间甚至需要磁盘交换动作辅助才能完成排序操作。这句话有两层含义,如果排序所依据的字段(一个或者多个)并没有创建索引,那么肯定无法基于索引完成排序;即使排序过程能够依据正确的索引完成,但是由于涉及到的查询结果太多,导致用于排序的内存空间不足,所以MySQL服务在进行排序时还会有磁盘交换动作。负责配置某一个客户(session)可用的内存空间参数项名字为“sort_buffer_size”。默认的大小为256KB,如果读者对查询结果集有特别要求,可以将该值改为1MB。一旦在Extra字段中出现了“Using filesort”提示,那么说明这条子查询也需要进行优化。
explain select * from myuser order by usersex +--------+-----------------------+ | ...... | Extra | +--------+-----------------------+ | ...... | Using filesort | +--------+-----------------------+ # 由于usersex并没有创建索引,所以使用filesort策略进行排序。
注意,在子查询中为Group By和Order by操作创建索引时,有时需要联合where关键字使用的查询字段一起创建复合索引才能起作用。这是因为子查询为了检索,所首先选择一个可用的索引项,随后进行排序时,却发现无法按照之前的索引进行排序,所以只有走filesort了。例如以下示例:
# user_name字段和user_number字段都独立创建了索引 explain select * from myuser where user_name = \'用户1\' group by user_number +--------+------------+----------------------------------------------------------+ | ...... | key | Extra | +--------+------------+----------------------------------------------------------+ | ...... | name_index | Using index condition; Using where; Using filesort | +--------+------------+----------------------------------------------------------+ # 为了首先完成条件检索,InnoDB引擎选择了user_name字段的索引 # 但是排序时发现无法按照之前的索引字段完成,所以选择走filesortUsing join buffer:使用InnoDB引擎预留的join buffer区域(一个专门用来做表连接的内存区域),这是一个正常现象主要涉及到两个子查询通过join关键字进行连接的操作。每一个客户端连接(session)独立使用的join buffer区域大小可以通过join_buffer_size参数进行设置。这个参数在MySQL 5.6 Version中的默认值为128KB。如果开发人员经常需要用到join操作,可以适当增加区域大小到1MB或者2MB。
# 以下语句是一个左外连接的操作 # 并且t_interfacemethod.uid和t_interfacemethod_param.interfacemethod之间有外键和索引存在 explain select * from t_interfacemethod_param left join t_interfacemethod on t_interfacemethod.uid = t_interfacemethod_param.interfacemethod +--------+----------------------------------------------------------+ | ...... | Extra | +--------+----------------------------------------------------------+ | ...... | | +--------+----------------------------------------------------------+ | ...... | Using where; Using join buffer (Block Nested Loop) | +--------+----------------------------------------------------------+
5-3、执行计划的局限性