EXPLAIN Output Format
EXPLAIN Output Interpretation
通过获取EXPLAIN输出的行列中的值的乘积,可以很好地指示连接有多好。这应该大致告诉您MySQL必须检查多少行才能执行查询。
如果使用max-join_size系统变量限制查询,则此行乘积还用于确定执行哪些多表SELECT语句以及中止哪些语句。请参阅第5.1.1节“配置服务器”。
以下示例显示了如何根据EXPLAIN提供的信息逐步优化多表连接。
假设您有此处显示的SELECT语句,并且您计划使用EXPLAIN对其进行检查:
For this example, make the following assumptions:
The columns being compared have been declared as follows.
最初,在执行任何优化之前,EXPLAIN语句会生成以下信息:
因为每个表的类型都是ALL,所以此输出表示MySQL正在生成所有表的笛卡尔积;即每一行的组合。这需要相当长的时间,因为必须检查每个表中行数的乘积。对于手头的案例,该产品为74×2135×74×3872=45268558720行。如果桌子更大,你只能想象需要多长时间。
这里的一个问题是,如果列被声明为相同的类型和大小,MySQL可以更有效地在列上使用索引。在这种情况下,如果VARCHAR和CHAR被声明为相同的大小,则它们被认为是相同的。tt.Actical PC被声明为CHAR(10),et.EMPLOYID为CHAR,因此存在长度不匹配。
要修复列长度之间的差异,请使用ALTER TABLE将ActualPC从10个字符延长到15个字符:
现在tt.AactualPC和et.MPLOYID都是VARCHAR(15)。再次执行EXPLAIN语句会产生以下结果:
这并不完美,但要好得多:行值的乘积减少了74倍。此版本将在几秒钟内执行。
可以进行第二次更改,以消除tt.AssignedPC=et_1.EMPLOYID和tt.ClientID=do.CUSTNMBR比较的列长度不匹配:
After that modification, EXPLAIN produces the output shown here:
此时,查询几乎尽可能地优化了。剩下的问题是,默认情况下,MySQL假设tt.ActualPC列中的值是均匀分布的,而tt表则不是这样。幸运的是,告诉MySQL分析密钥分布很容易:
With the additional index information, the join is perfect and EXPLAIN produces this result:
EXPLAIN输出中的行列是MySQL连接优化器的一个有根据的猜测。通过将行乘积与查询返回的实际行数进行比较,检查这些数字是否接近真实值。如果数字相差很大,在SELECT语句中使用STRIGHT_JOIN并尝试在FROM子句中以不同的顺序列出表,可能会获得更好的性能。(但是,STRIGHT_JOIN可能会阻止使用索引,因为它禁用了半连接转换。请参阅第8.2.2.1节“使用半连接转换优化子查询、派生表和视图引用”。)
在某些情况下,当EXPLAIN SELECT与子查询一起使用时,可以执行修改数据的语句;有关更多信息,请参阅第13.2.10.8节“衍生表”。