SQL_explain操作解釋

explain用法

爲了方便理解,一邊操作,一邊講述。

首先創建一個數據表,並增加索引(主鍵、聯合索引):

create table test_union
(
    id int auto_increment comment 'zhuji' primary key,
    k1 int not null comment 'lianheziduan1',
    k2 int not null comment 'lianheziduan2',
    k3 int not null comment 'lianheziduan3',
    k4 int not null comment 'lianheziduan4',
    k5 int not null comment 'lianheziduan5',
    k6 int null comment 'ziduan1',
    k7 int null comment 'ziduan2'
)
;

create index test_union_k1_k2_k3_k4_k5_index
    on test_union (k1, k2, k3, k4, k5)
;

create table table_union_fk
(
    id int auto_increment comment '主鍵' primary key,
    name varchar(20) default '' not null comment '名稱',
    fk_id int default '0' not null
)
;

注:這裏爲了省事,所有字段的註釋爲漢語拼音。

插入幾條數據:

insert into test_union(k1,k2,k3,k4,k5,k6,k7) values(1,1,1,1,1,1,1);
insert into test_union(k1,k2,k3,k4,k5,k6,k7) values(2,2,2,2,2,2,2);
insert into test_union(k1,k2,k3,k4,k5,k6,k7) values(3,3,3,3,3,3,3);

insert into table_union_fk(name,fk_id) values('1',1);
insert into table_union_fk(name,fk_id) values('2',2);

explain語句顯示的字段,這裏先執行一下:
explain select * from test_union where id = 1
結果是:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE test_union const PRIMARY PRIMARY 4 const 1

所以一共有10個字段。下面介紹筆者對每一個字段的理解。

1. id

是select語句查詢的序列號;
當查詢語句比較複雜的時候會產生多個序列號,如:
EXPLAIN SELECT * FROM test_union WHERE id = (SELECT id FROM test_union WHERE id = 3);
結果是:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union const PRIMARY PRIMARY 4 const 1
2 SUBQUERY test_union const PRIMARY PRIMARY 4 1 Using index

2. select_type

select語句的類型,包括SIMPLEPRIMARYUNIONDEPENDENT UNIONUNION RESULTSUBQUERYDEPENDENT SUBQUERYDERIVEDMATERIALIZEDUNCACHEABLE SUBQUERYUNCACHEABLE UNION

2.1 SIMPLE

簡單的SELECT語句(不包括UNION操作和子查詢操作)。例:
explain select * from test_union where id = 1
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE test_union const PRIMARY PRIMARY 4 const 1

2.2 PRIMARY

最外層的SELECT語句(如果兩表做UNION或者存在子查詢的時候,最外層的操作爲PRIMARY)。例:
EXPLAIN SELECT * FROM test_union WHERE id = (SELECT id FROM test_union WHERE id = 3);
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union const PRIMARY PRIMARY 4 const 1
2 SUBQUERY test_union const PRIMARY PRIMARY 4 1 Using index

2.3 UNION

UNION操作中,查詢中處於內層的SELECT(內層的SELECT語句與外層的SELECT語句沒有依賴關係)。例:
EXPLAIN SELECT * FROM test_union WHERE id = 1 UNION SELECT * FROM test_union WHERE id = 2;
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union const PRIMARY PRIMARY 4 const 1
2 UNION test_union const PRIMARY PRIMARY 4 const 1
<null> UNION RESULT <union1,2> ALL <null> <null> <null> <null> <null>

2.4 DEPENDENT UNION

UNION操作中,查詢中處於內層的SELECT(內層的SELECT語句與外層的SELECT語句有依賴關係)。例:
EXPLAIN SELECT * FROM test_union WHERE id in (SELECT id FROM test_union WHERE id = 3 UNION SELECT id FROM test_union WHERE id = 1);
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union ALL <null> <null> <null> <null> 3 Using where
2 DEPENDENT SUBQUERY test_union const PRIMARY PRIMARY 4 const 1 Using index
3 DEPENDENT UNION test_union const PRIMARY PRIMARY 4 const 1 Using index
<null> UNION RESULT <union1,2> ALL <null> <null> <null> <null> <null>

2.5 UNION RESULT

UNION操作的結果,id值通常爲NULL。例:
EXPLAIN SELECT * FROM test_union WHERE id = 1 UNION SELECT * FROM test_union WHERE id = 2;
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union const PRIMARY PRIMARY 4 const 1
2 UNION test_union const PRIMARY PRIMARY 4 const 1
<null> UNION RESULT <union1,2> ALL <null> <null> <null> <null> <null>

2.6 SUBQUERY

子查詢中首個SELECT(如果有多個子查詢存在)。例:
EXPLAIN SELECT * FROM test_union WHERE id = (SELECT fk_id FROM table_union_fk WHERE table_union_fk.id = 1);
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union const PRIMARY PRIMARY 4 const 1
2 SUBQUERY table_union_fk const PRIMARY PRIMARY 4 1

2.7 DEPENDENT SUBQUERY

子查詢中首個SELECT(如果有多個子查詢存在)。例:
EXPLAIN SELECT * FROM test_union WHERE id in (SELECT id FROM test_union WHERE id = 3);
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY test_union ALL <null> <null> <null> <null> 3 Using where
2 DEPENDENT SUBQUERY test_union const PRIMARY PRIMARY 4 const 1 Using index

2.8 DERIVED

被驅動的SELECT子查詢(子查詢位於FROM子句)。例:
EXPLAIN SELECT id,k1 FROM (SELECT * FROM test_union WHERE id < 3) a WHERE id = 2;
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL <null> <null> <null> <null> 2 Using where
2 DERIVED test_union range PRIMARY PRIMARY 4 const 2 Using where

2.9 MATERIALIZED

被物化的子查詢。

2.10 UNCACHEABLE SUBQUERY

對於外層的主表,子查詢不可被物化,每次都需要計算(耗時操作)。

2.11 UNCACHEABLE UNION

UNION操作中,內層的不可被物化的子查詢(類似於UNCACHEABLE SUBQUERY)。

:物化的概念還不清楚,所以這裏暫作留存,以後補充。

3. table

輸出的行所引用的表。

4. type

顯示的是訪問類型,是較爲重要的一個指標,結果值從好到壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL。 一般來說,得保證查詢至少達到range級別,最好能達到ref。

4.1 NULL

當SQL不訪問表或者索引就能獲得結果。例:
EXPLAIN SELECT SYSDATE();
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <null> <null> <null> <null> <null> <null> <null> No tables used

4.2 const

當MySQL對查詢某部分進行優化,這個匹配的行的其他列值可以轉換爲一個常量來處理。如將主鍵或者唯一索引置於where列表中,MySQL就能將該查詢轉換爲一個常量。例:
EXPLAIN SELECT * FROM test_union WHERE id = 1;
結果:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE test_union const PRIMARY PRIMARY 4 const 1

system是const的一個特例,但是筆者還不是很理解,未能找到例子。

4.3 eq_ref

參與連接運算的表是內表(在代碼實現的算法中,兩表連接時作爲循環中的內循環遍歷的對象,這樣的表稱爲內表)。基於索引(連接字段上存在唯一索引或者主鍵索引,且操作符必須是“=”謂詞,索引值不能爲NULL)做掃描,使得對外表的一條元組,內表只有唯一一條元組與之對應。

4.4 ref

可以用於單表掃描或者連接。參與連接運算的表,是內表。基於索引(連接字段上的索引是非唯一索引,操作符必須是“=”謂詞,連接字段值不可爲NULL)做掃描,使得對外表的一條元組,內表可有若干條元組與之對應。

4.5 range

索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行,常見於between、<、>等的查詢。等同於Oracle的index range scan。

4.6 index

MySQL採取索引全掃描的方式來返回數據行,等同於Oracle的full index scan。

4.7 all

全表掃描或者範圍掃描:不使用索引,順序掃描,直接讀取表上的數據(訪問數據文件)。

5. possible_keys

指出MySQL能使用哪個索引在該表中找到行。如果是空的,沒有相關的索引。這時要提高性能,可通過檢驗WHERE子句,看是否引用某些字段,或者檢查字段不是適合索引。

6. key

顯示MySQL實際決定使用的鍵。如果沒有索引被選擇,鍵是NULL。

7. key_len

顯示MySQL決定使用的鍵長度。如果鍵是NULL,長度就是NULL。文檔提示特別注意這個值可以得出一個多重主鍵裏mysql實際使用了哪一部分。這裏注意了,一般索引中一個字段是4或者5,區別是在於如果字段允許爲null,則一個字段的長度是5,如果不允許爲null,則一個字段的長度爲4。

8. ref

顯示哪個字段或常數與key一起被使用。

9. rows

這個數表示mysql要遍歷多少數據才能找到,在innodb上是不準確的。

10. Extra

如果是Only index,這意味着信息只用索引樹中的信息檢索出的,這比掃描整個表要快。
如果是where used,就是使用上了where限制。
如果是impossible where 表示用不着where,一般就是沒查出來啥。
如果此信息顯示Using filesort或者Using temporary的話會很吃力,WHERE和ORDER BY的索引經常無法兼顧,如果按照WHERE來確定索引,那麼在ORDER BY時,就必然會引起Using filesort,這就要看是先過濾再排序划算,還是先排序再過濾划算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章