3.1 MYSQL数据库的SQL执行计划解释器
EXPLAIN tbl_name
或者如下:
EXPLAIN [EXTENDED] SELECT select_options
EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name的一个同义词。
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。mysql> explain a;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | UNI | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.02 sec)
![]()
mysql> explain t;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | 0 | |
| MC | varchar(60) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
![]()
mysql> select * from t;
+-------+------+
| id | MC |
+-------+------+
| 1 | MC |
| 2 | NULL |
| 3 | NULL |
| 4 | NULL |
| 5 | NULL |
| 6 | NULL |
| 7 | NULL |
| 8 | NULL |
| 9 | NULL |
| 10000 | MC |
+-------+------+
10 rows in set (0.00 sec)
![]()
mysql> select * from a;
+------+
| id |
+------+
| NULL |
| 1 |
| 2 |
+------+
3 rows in set (0.00 sec)
![]()
mysql> explain select * from A where id in (select id from T)\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: A
type: index
possible_keys: NULL
key: idx_a
key_len: 5
ref: NULL
rows: 3
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: T
type: unique_subquery
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: func
rows: 1
Extra: Using index
2 rows in set (0.02 sec)
index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:
mysql> explain select * from test where id in (select id from a)\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: test
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1534755
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: a
type: index_subquery
possible_keys: idx_a
key: idx_a
key_len: 5
ref: func
rows: 1
Extra: Using index
2 rows in set (0.00 sec)
range
索引范围扫描,只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range:
mysql> explain select * from t where id=1 or id=10000 or id=3\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)
![]()
mysql> explain select * from t where id<=3\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 4
Extra: Using where
1 row in set (0.00 sec)
![]()
ERROR:
No query specified
index
索引全扫描,该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。
mysql> explain select * from t\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: index
possible_keys: NULL
key: idx_t_mc
key_len: 63
ref: NULL
rows: 10
Extra: Using index
1 row in set (0.00 sec)
![]()
ERROR:
No query specified
ALL
全表扫描,对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记cnst的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。
pssible_keysmysql> explain select * from test\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1534755
Extra:
1 row in set (0.06 sec)
![]()
ERROR:
No query specified
pssible_keys列指出MySQL能使用哪个索引在该表中找到行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在pssible_keys中的某些键实际上不能按生成的表次序使用。如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询。
为了看清一张表有什么索引,使用SHOW INDEX FROM tbl_name。
keymysql> show index from t;
+-------+------------+----------+--------------+-------------+-----------+------
-------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardi
nality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+------
-------+----------+--------+------+------------+---------+
| t | 0 | PRIMARY | 1 | id | A |
2 | NULL | NULL | | BTREE | |
| t | 1 | idx_t_mc | 1 | MC | A |
2 | NULL | NULL | YES | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+------
-------+----------+--------+------+------------+---------+
2 rows in set (0.08 sec)
![]()
key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL使用或忽视pssible_keys列中的索引,在查询中使用FRCE INDEX、USE INDEX或者IGNRE INDEX。对于MyISAM和BDB表,运行ANALYZE TABLE可以帮助优化器选择更好的索引。对于MyISAM表,可以使用myisamchk --analyze。
key_lenmysql> explain select * from t where id=1 or mc='1'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: index
possible_keys: PRIMARY,idx_t_mc
key: idx_t_mc
key_len: 63
ref: NULL
rows: 10
Extra: Using where; Using index
1 row in set (0.00 sec)
![]()
mysql> explain select * from t ignore index(idx_t_mc) where id=1 or mc='1'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 10
Extra: Using where
1 row in set (0.00 sec)
key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。注意通过key_len值我们可以确定MySQL将实际使用一个多部关键字的几个部分。
ref
ref列显示使用哪个列或常数与key一起从表中选择行。
rows
rows列显示MySQL认为它执行查询时必须检查的行数。
Extra
该列包含MySQL解决查询的详细信息。下面解释了该列可以显示的不同的文本字符串:
Distinct
MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
Not exists
MySQL能够对查询进行LEFT JIN优化,发现1个匹配LEFT JIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
当使用EXTENDED关键字时,EXPLAIN产生附加信息,可以用SHOW WARNINGS浏览。该信息显示优化器限定SELECT语句中的表和列名,重写并且执行优化规则后SELECT语句是什么样子,并且还可能包括优化过程的其它注解。
