標籤:mysql sql 最佳化
EXPLAIN語句能夠被用於擷取一些關於SQL執行時的相關資訊,比如表的串連順序,對錶的方式方式等等。通過對該相關資訊進行進一步的分析,我們 可以通過對錶添加適當的索引,以及最佳化串連順序,使用提示等等手段來達到使SQL高效啟動並執行目的。本文描述了EXPLAIN的用法並給出了相關樣本。
一、EXPLAIN概述
EXPLAIN 語句主要是用於解析SQL執行計畫,通過分析執行計畫採取適當的最佳化方式提高SQL啟動並執行效率。EXPLAIN 語句輸出通常包括id列,select_type,table,type,possible_keys,key等等列資訊MySQL 5.6.3後支援SELECT, DELETE, INSERT,REPLACE, and UPDATE. EXPLAIN EXTENDED支援一些額外的執行計畫相關的資訊EXPLAIN PARTITIONS支援基於分區表查詢執行計畫的相關資訊
二、EXPLAIN輸出資料行描述
-- 下面通過樣本來展示EXPLAIN輸出資料行([email protected]) [sakila]> explain select sum(amount) from customer a, -> payment b where 1=1 and a.customer_id=b.customer_id and -> email=‘[email protected]‘\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: a type: ALLpossible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 590 Extra: Using where*************************** 2. row *************************** id: 1 select_type: SIMPLE table: b type: refpossible_keys: idx_fk_customer_id key: idx_fk_customer_id key_len: 2 ref: sakila.a.customer_id rows: 14 Extra:
1、各列表示的意義
Column Meaning------ ------------------------------------id The SELECT identifier select_type The SELECT typetable The table for the output rowpartitions The matching partitionstype The join typepossible_keys The possible indexes to choosekey index actually chosenkey_len The length of the chosen keyref The columns compared to the indexrows Estimate of rows to be examinedfiltered Percentage of rows filtered by table conditionExtra Additional information
2、各列上的具體描述
id: 包含一組數字,表示查詢中執行select子句或動作表的順序 id相同,執行順序由上至下,否則id值越大(通常子查詢會產生)優先順序越高,越先被執行 id如果相同,可以認為是一組,從上往下順序執行;在所有組中,id值越大,優先順序越高,越先執行select_type: 表示查詢中每個select子句的類型(簡單 OR複雜) select_type Value Meaning ------------- ----------------------------------------------- SIMPLE Simple SELECT (not using UNION or subqueries) PRIMARY Outermost SELECT 最外層select UNION Second or later SELECT statement in a UNION DEPENDENT UNION Second or later SELECT statement in a UNION, dependent on outer query UNION RESULT Result of a UNION. SUBQUERY First SELECT in subquery DEPENDENT SUBQUERY First SELECT in subquery, dependent on outer query(通常為相互關聯的子查詢) DERIVED Derived table SELECT (subquery in FROM clause) MATERIALIZED Materialized subquery UNCACHEABLE SUBQUERY A subquery for which the result cannot be cached and must be reevaluated for each row of the outer query UNCACHEABLE UNION The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY) table: 從哪個表(表名)上輸出行記錄,也可能是下列值: ? <unionM,N>: The row refers to the union of the rows with id values of M and N. ? <derivedN>: The row refers to the derived table result for the row with an id value of N. A derived table may result, for example, from a subquery in the FROM clause. ? <subqueryN>: The row refers to the result of a materialized subquery for the row with an id value of N. partitions: 查詢匹配的記錄來自哪一個分區,當使用EXPLAIN,分區PARTITIONS關鍵字被指定時type: 連線類型 system 表只有一行 const 表最多隻有一行匹配,通用用於主鍵或者唯一索引比較時 eq_ref 每次與之前的表合并行都只在該表讀取一行,這是除了system,const之外最好的一種, 特點是使用=,而且索引的所有部分都參與join且索引是主鍵或非空唯一鍵的索引 ref 如果每次只匹配少數行,那就是比較好的一種,使用=或<=>,可以是左覆蓋索引或非主鍵或非唯一鍵 fulltext 全文檢索搜尋 ref_or_null 與ref類似,但包括NULL index_merge 表示出現了索引合并最佳化(包括交集,並集以及交集之間的並集),但不包括跨表和全文索引。 這個比較複雜,目前的理解是合并單表的範圍索引掃描(如果成本估算比普通的range要更優的話) unique_subquery 在in子查詢中,就是value in (select...)把形如“select unique_key_column”的子查詢替換。 PS:所以不一定in子句中使用子查詢就是低效的! index_subquery 同上,但把形如”select non_unique_key_column“的子查詢替換 range 常數值的範圍 index a.當查詢是索引覆蓋的,即所有資料均可從索引樹擷取的時候(Extra中有Using Index); b.以索引順序從索引中尋找資料行的全表掃描(無 Using Index); c.如果Extra中Using Index與Using Where同時出現的話,則是利用索引尋找索引值的意思; d.如單獨出現,則是用讀索引來代替讀行,但不用於尋找 all 全表掃描possible_keys: 指出MySQL能使用哪個索引在表中找到行。 查詢涉及到的欄位上若存在索引則該索引將被列出,但不一定被查詢使用。 如果改列為NULL,說明該查詢不會使用到當前表上的相關索引,考慮是否有必要添加索引key 顯示MySQL在查詢中實際使用的索引,若沒有使用索引,顯示為NULL 也可能存在key不等於possible_keys的情形,即possible_keys不適合提取所需的行 而查詢所選擇的列在使用其他索引時更高效 TIPS:查詢中若使用了覆蓋索引,則該索引僅出現在key列表中key_len 表示索引中使用的位元組數,可通過該列計算查詢中使用的索引的長度ref 表示上述表的串連匹配條件,即哪些列或常量被用於尋找索引列上的值rows 表示MySQL根據表統計資訊及索引選用情況,估算的找到所需的記錄所需要讀取的行數 對於InnoDB,該值為預估,不一定精確Extra 包含不適合在其他列中顯示但十分重要的額外資訊
三、使用EXPLAIN EXTENDED 樣本
([email protected]) [sakila]> explain extended select * from city where country_id in -> ( select country_id from country where country=‘China‘) and 1=1 \G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: country type: ALLpossible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 109 filtered: 100.00 Extra: Using where*************************** 2. row *************************** id: 1 select_type: SIMPLE table: city type: refpossible_keys: idx_fk_country_id key: idx_fk_country_id key_len: 2 ref: sakila.country.country_id rows: 1 filtered: 100.00 Extra: NULL2 rows in set, 1 warning (0.00 sec)([email protected]) [sakila]> show warnings\G*************************** 1. row *************************** Level: Note Code: 1003Message: /* select#1 */ select `city`.`city_id` AS `city_id`,`city`.`city` AS `city`,`city`.`country_id` AS `country_id`,`city`.`last_update` AS `last_update` from `sakila`.`country` join `sakila`.`city` where ((`city`.`country_id` = `country`.`country_id`) and (`country`.`country` = ‘China‘))1 row in set (0.00 sec)-- 從上面的extended使用可以看出,查詢中多出了filtered列-- 其次原來的SQL語句真正在執行的時候被改寫,即原來的1=1的條件被去掉-- 對於複雜的SQL語句我們可以通過該方式獲得一個比較清晰的真正被執行的SQL語句
四、EXPLAIN PARTITIONS樣本
([email protected]) [sakila]> CREATE TABLE `actor_part` ( -> `actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, -> `first_name` varchar(45) NOT NULL, -> `last_name` varchar(45) NOT NULL, -> `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -> PRIMARY KEY (`actor_id`), -> KEY `idx_actor_last_name` (`last_name`) -> ) partition by hash(actor_id) partitions 4;Query OK, 0 rows affected (0.11 sec)([email protected]) [sakila]> insert into actor_part select * from actor;Query OK, 200 rows affected (0.02 sec)Records: 200 Duplicates: 0 Warnings: 0([email protected]) [sakila]> explain select * from actor_part where actor_id=10; -- 未使用partitions時+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------+| 1 | SIMPLE | actor_part | const | PRIMARY | PRIMARY | 2 | const | 1 | NULL |+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------+1 row in set (0.00 sec)([email protected]) [sakila]> explain partitions select * from actor_part where actor_id=10; -- 使用partitions時+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+-------+| 1 | SIMPLE | actor_part | p2 | const | PRIMARY | PRIMARY | 2 | const | 1 | NULL |+----+-------------+------------+------------+-------+---------------+---------+---------+-------+------+-------+1 row in set (0.00 sec)-- 多出了partitions列
五、參考:
MySQL reference manual 5.6其他個人部落格
著作權聲明:本文為博主原創文章,歡迎擴散,擴散請務必註明出處。
MySQL EXPLAIN SQL 輸出資訊描述