MYSQL EXPLAIN查看MYSQL执行SELECT语句的优化
该表没有唯一字段。单元格编辑、复选框、编辑、复制和删除无法正常使用。
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
1 | SIMPLE | zyd_admin_role_priv | ALL | NULL | NULL | NULL | NULL | 319 |
|
|
借助于EXPLAIN,可以知道什么时候必须为表加入索引以得到一个使用索引来寻找记录的更快的SELECT。
如果由于使用不正确的索引出现了问题,应运行ANALYZE TABLE更新表的统计(例如关键字集的势),这样会影响优化器进行的选择。
EXPLAIN为用于SELECT语句中的每个表返回一行信息。表以它们在处理查询过程中将被MySQL读入的顺序被列出。MySQL用一遍扫描多次联接(single-sweep multi-join)的方式解决所有联接。这意味着MySQL从第一个表中读一行,然后找到在第二个表中的一个匹配行,然后在第3个表中等等。当所有的表处理完后,它输出选中的列并且返回表清单直到找到一个有更多的匹配行的表。从该表读入下一行并继续处理下一个表。
ID字段:标注不同表的编号
Select_type:select查询类型
可以为一下值:
SIMPLE:简单查询不实用UNION
PRIMARY
UNION
DEPENDENT UNION
UNION RESULT
DERIVED
DEPENDENT SUBQUERY
Table:表示当前表
type:重要字段
联接类型。下面给出各种联接类型,按照从最佳类型到最坏类型进行排序:
查询条件类型:
System:系统类型
表仅有一行(=系统表)。这是const联接类型的一个特例
Const:类型 表示表最多只有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!
const用于用常数值比较PRIMARY KEY或UNIQUE索引的所有部分时。
如:SELECT * FROM table WHERE PRIMARY KEY=1;
SELECT * FROM table WHERE unique1=1 AND unique2=2;
eq_ref: 对于每个来自前表的组合这可能是最好的组合方式,从前表至返回一行数据,且是基于前表的PRIMARY KEY或UNIQUE索引:
SELECT * FROM table,table1 WHERE table.clo1=table2.clo;
SELECT * FROM table,table1 WHERE table.clo1=table2.clo AND table.clo1= 1;
Ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取,如果使用的键仅仅匹配少量行,该联接类型是不错的,ref可以用于使用=或<=>操作符的带索引的列
SELECT * FROM table,table1 WHERE table.clo1=table2.clo;
SELECT * FROM table,table1 WHERE table.clo1=table2.clo AND table.clo1= 1;
ref_or_null:和ref一样,只是增加了搜索为NULL的列
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
index_merge:
使用索引合并优化,key列包含了使用的索引的清单,key_len 包含了使用的索引的最长的关键元素
unique_subquery:该类型替换了下面形式的IN子查询的ref
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
index_subquery:该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引
value IN (SELECT key_column FROM single_table WHERE some_expr)
Range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素在该类型中ref列为NULL
当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range
SELECT * FROM tbl_name
WHERE key_part1= 10 AND key_part2 IN (10,20,30);
SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;
Index:全部扫描只是扫描索引树通常比all快。
ALL:全部扫描表非常糟糕的方式
Key:
显示查询所使用的索引列
对于MyISAM和BDB表,运行ANALYZE TABLE可以帮助优化器选择更好的索引
key_len:
显示索引长度
Ref:
显示那些索引使用常数来筛选
Rows:返回的数据行数
Extra:对于此次查询的详细描述
Distinct发现一个行后停止为当前行组合搜索更多的行。
NOT exists:MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行.
SELECT * 从t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL
假定t2.id定义为NOT NULL。在这种情况下,MySQL使用t1.id的值扫描t1并查找t2中的行。如果MySQL在t2中发现一个匹配的行,它知道t2.id绝不会为NULL,并且不再扫描t2内有相同的id值的行。换句话说,对于t1的每个行,MySQL只需要在t2中查找一次,无论t2内实际有多少匹配的行。
range checked for each record (index map: #):
MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。对前面的表的每个行组合,MySQL检查是否可以使用range或index_merge访问方法来索取行.这并不很快,但比执行没有索引的联接要快得多。
Using filesort:MySQL需要额外的一次传递,以找出如何按排序顺序检索行。通过根据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行
Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。当查询只使用作为单一索引一部分的列时,可以使用该策略
Using where:WHERE子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。