3. 通过 EXPLAIN 分析低效 SQL 的执行计划
可以通过 EXPLAIN 或者 DESC 命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。
select_type:表示 SELECT 的类型,常见的取值有:
SIMPLE(简单表,即不使用表连接或者子查询)
PRIMARY(主查询,即外层的查询)
UNION(UNION 中的第二个或者后面的查询语句)
SUBQUERY(子查询中的第一个 SELECT)
table:输出结果集的表。
type:表示 MySQL 在表中找到所需行的方式,或者叫访问类型。
possible_keys:表示查询时可能使用的索引。
key:表示实际使用的索引。
key_len:使用到索引字段的长度。
rows:扫描行的数量。
Extra:执行情况的说明和描述,包含不适合在其他列中显示但是对执行计划非常重要的额外信息。
type
表示 MySQL 在表中找到所需行的方式,或者叫访问类型,常见的类型有:
类型 type 还有其他值,如 ref_or_null(与 ref 类似,区别在于条件中包含对 NULL 的查询)、index_merge(索引合并优化)、unique_subquery(in 的后面是一个查询主键字段的子查询)、index_subquery(与 unique_subquery 类似,区别在于 in 的后面是查询非唯一索引字段的子查询)等。
Extra
Using index:表示 MySQL 将使用覆盖索引,以避免回表。
Using where:表示会在存储引擎检索之后再进行过滤。
Using temporary:表示会使用一个临时表。
Using filesort:表示对查询结果进行了排序。
EXPLAIN EXTENDED
MySQL 4.1 开始引入了 explain extended 命令,通过 explain extended 加上 show warnings,能够看到在 SQL 真正被执行之前优化器做了哪些 SQL 改写。
EXPLAIN EXTENDED
SELECT sum(amount)
FROM customer a,
payment b
WHERE 1 = 1
AND a.customer_id = b.customer_id
AND email = 'JANE.BENNETT@sakilacustomer.org' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: const
possible_keys: PRIMARY,uk_email
key: uk_email
key_len: 203
ref: const
rows: 1
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: b
partitions: NULL
type: ref
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: const
rows: 28
filtered: 100.00
Extra: NULL
2 rows in set, 2 warnings (0.00 sec)
SHOW WARNINGS\G;
*************************** 1. row ***************************
Level: Warning
Code: 1681
Message: 'EXTENDED' is deprecated and will be removed in a future release.
*************************** 2. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select sum(`sakila`.`b`.`amount`) AS `sum(amount)` from `sakila`.`customer` `a` join `sakila`.`payment` `b` where ((`sakila`.`b`.`customer_id` = '77') and ('JANE.BENNETT@sakilacustomer.org' = 'JANE.BENNETT@sakilacustomer.org'))
WARNING信息中的SQL语句美化后,如下所示:
/* select#1 */
SELECT sum(`sakila`.`b`.`amount`) AS `sum(amount)`
FROM `sakila`.`customer` `a`
JOIN `sakila`.`payment` `b`
WHERE ((
`sakila`.`b`.`customer_id` = '77'
)
AND ('JANE.BENNETT@sakilacustomer.org' = 'JANE.BENNETT@sakilacustomer.org'))
最后更新于