【mysql 5.7】Explain工具介紹-筆記
文章目錄
1. Explain工具介紹
使用EXPLAIN關鍵字可以模擬優化器執行SQL語句,分析你的查詢語句或是結構的效能瓶頸在 select 語句之前增加 explain 關鍵字,MySQL 會在查詢上設定一個標記,執行查詢會返回執行計劃的資訊,而不是執行這條SQL注意:如果 from 中包含子查詢,仍會執行該子查詢,將結果放入臨時表中
1.1 Explain分析示例
參考官方文件:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
DROP TABLE IF EXISTS `actor`; CREATE TABLE `actor` ( `id` int(11) NOT NULL, `name` varchar(45) DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 INSERT INTO `actor` (`id`, `name`, `update_time`) VALUES (1,'a','2017-12-22 15:27:18'), (2,'b','2017-12-22 15:27:18'), (3,'c','2017-12-22 15:27:18'); DROP TABLE IF EXISTS `film`; CREATE TABLE `film` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 INSERT INTO `film` (`id`, `name`) VALUES (3,'film0'),(1,'film1'),(2,'film2'); DROP TABLE IF EXISTS `film_actor`; CREATE TABLE `film_actor` ( `id` int(11) NOT NULL, `film_id` int(11) NOT NULL, `actor_id` int(11) NOT NULL, `remark` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_film_actor_id` (`film_id`,`actor_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 INSERT INTO `film_actor` (`id`, `film_id`, `actor_id`) VALUES (1,1,1),(2,1,2),(3,2,1);
EXPLAIN SELECT * FROM actor;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra ------ ----------- ------ ---------- ------ ------------- ------ ------- ------ ------ -------- -------- 1 SIMPLE actor (NULL) ALL (NULL) (NULL) (NULL) (NULL) 3 100.00 (NULL)
在查詢中的每個表會輸出一行,如果有兩個表通過 join
連線查詢,那麼會輸出兩行
1.2 explain 兩個變種
1)explain extended
:會在 explain 的基礎上額外提供一些查詢優化的資訊。緊隨其後通過 show warnings
命令可以得到優化後的查詢語句
,從而看出優化器優化了什麼。
額外還有 filtered 列,是一個半分比的值,rows * filtered/100
可以估算出將要和 explain 中前一個表進行連線的行數(前一個表指 explain 中的id值比當前表id值小的表)。
將要被廢棄,比如5.7,不帶extended,預設就會顯示filtered 列
show warnings
命令可以在任意sql語句之後,不必要非在Explain之後,比如檢視時間SELECT NOW();
執行一下語句:
EXPLAIN EXTENDED SELECT * FROM film WHERE id = 1;
執行結果:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
------ ----------- ------ ---------- ------ ------------- ------- ------- ------ ------ -------- --------
1 SIMPLE film (NULL) const PRIMARY PRIMARY 4 const 1 100.00 (NULL)
執行:
show warnings;
執行結果:
2)explain partitions
:相比 explain 多了個 partitions
欄位,如果查詢是基於分割槽表的話,會顯示查詢將訪問的分割槽。
作用不大。5.7版本預設攜帶
partitions
欄位
2. explain中的列
接下來我們將展示 explain 中每個列的資訊。
2.1 id列
id列的編號是 select 的序列號,有幾個 select 就有幾個id,並且id的順序是按 select 出現的順序增長的。
id列越大執行優先順序越高,id相同則從上往下執行,id為NULL最後執行。
對子查詢包括父查詢,進行編號
2.2 select_type列
select_type 表示對應行是簡單還是複雜的查詢。
simple:簡單查詢。
查詢不包含子查詢和union
mysql> explain select * from film where
primary
複雜查詢中最外層的 select
subquery
包含在 select 中的子查詢(不在 from 子句中
)
derived:
包含在 from 子句中的子查詢
。MySQL會將結果存放在一個臨時表中,也稱為派生表(derived的英文含義)
用這個例子來了解 primary、subquery 和 derived 類:
mysql> set session optimizer_switch='derived_merge=off'; #關閉mysql5.7新特性對衍生表的合併優化
mysql> explain select (select 1 from actor where id = 1) from (select * from film where id = 1) der;
注意:需要關閉mysql5.7新特性對衍生表的合併優化
還原預設配置:
mysql> set session optimizer_switch='derived_merge=on'; #還原預設配置
union:
在 union 中的第二個或後面的 select
mysql> explain select 1 union all select 1;
2.3. table列
這一列表示 explain 的一行正在訪問哪個表。
類似一個指標,指向某個表,如果表的位置是個子句,那麼就是子句的下標
當 from 子句中有子查詢時,table列是 <derivenN>
格式,表示當前查詢依賴 id=N 的查詢,於是先執行 id=N 的查詢。
參見derived:章節的例子:
當有 union 時,UNION RESULT 的 table 列的值為<union1,2>,1和2表示參與 union 的 select 行id。
2.4. type列
這一列表示關聯型別或訪問型別
,即MySQL決定如何查詢表中的行,查詢資料行記錄的大概範圍。
依次從最優到最差分別為:system > const > eq_ref > ref > range > index > ALL
一般來說,得保證查詢達到range級別,最好達到ref
2.4.1 NULL
mysql能夠在優化階段分解查詢語句,在執行階段用不著再訪問表或索引
。例如:在索引列中選取最小值,可以單獨查詢索引來完成,不需要在執行時訪問表
mysql> explain select min(id) from film;
2.4.2 const, system:
mysql能對查詢的某部分進行優化並將其轉化成一個常量
(可以看show warnings 的結果)。
用於primary key
或 unique key
的所有列與常數比較時,所以表最多有一個匹配行,讀取1次,速度比較快。
system是const的特例,表裡只有一條元組匹配時為system
mysql> SET SESSION optimizer_switch='derived_merge=off'
mysql> explain extended select * from (select * from film where id = 1) tmp;
mysql> show warnings;
2.4.2 eq_ref
primary key
或 unique key
索引的所有部分被連線使用 ,最多隻會返回一條符合條件的記錄。這可能是在const 之外最好的聯接型別了,簡單的 select 查詢不會出現這種 type
。
mysql> explain select * from film_actor left join film on film_actor.film_id = film.id;
參考:
參考主體