mysql explain用法和結果的含義

簡述

 

使用EXPLAIN關鍵字能夠模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸。如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。mysql

 

經過EXPLAIN,咱們能夠分析出如下結果:sql

  • 表的讀取順序
  • 數據讀取操做的操做類型
  • 哪些索引可使用
  • 哪些索引被實際使用
  • 表之間的引用
  • 每張表有多少行被優化器查詢

 

使用方式以下:express

EXPLAIN +SQL語句

 

執行計劃包含的信息 函數

+----+-------------+---------+------+---------------+------+---------+------+--------+----------+-------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra | 
+----+-------------+---------+------+---------------+------+---------+------+--------+----------+-------+

 

 執行計劃各字段含義:性能

 

id SELECT識別符。這是SELECT的查詢序列號
select_type

SELECT類型,能夠爲如下任何一種:優化

  • SIMPLE:簡單SELECT(不使用UNION或子查詢)
  • PRIMARY:最外面的SELECT
  • UNION:UNION中的第二個或後面的SELECT語句
  • DEPENDENT UNION:UNION中的第二個或後面的SELECT語句,取決於外面的查詢
  • UNION RESULT:UNION 的結果
  • SUBQUERY:子查詢中的第一個SELECT
  • DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決於外面的查詢
  • DERIVED:導出表的SELECT(FROM子句的子查詢)
table

輸出的行所引用的表 (指的就是當前執行的表)spa

type

聯接類型。下面給出各類聯接類型,按照從最佳類型到最壞類型進行排序:設計

  • system:表僅有一行(=系統表)。這是const聯接類型的一個特例。
  • const:表最多有一個匹配行,它將在查詢開始時被讀取。由於僅有一行,在這行的列值可被優化器剩餘部分認爲是常數。const表很快,由於它們只讀取一次!
  • eq_ref:對於每一個來自於前面的表的行組合,從該表中讀取一行。這多是最好的聯接類型,除了const類型。
  • ref:對於每一個來自於前面的表的行組合,全部有匹配索引值的行將從這張表中讀取。
  • ref_or_null:該聯接類型如同ref,可是添加了MySQL能夠專門搜索包含NULL值的行。
  • index_merge:該聯接類型表示使用了索引合併優化方法。
  • unique_subquery:該類型替換了下面形式的IN子查詢的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery是一個索引查找函數,能夠徹底替換子查詢,效率更高。
  • index_subquery:該聯接類型相似於unique_subquery。能夠替換IN子查詢,但只適合下列形式的子查詢中的非惟一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
  • range:只檢索給定範圍的行,使用一個索引來選擇行。
  • index:該聯接類型與ALL相同,除了只有索引樹被掃描。這一般比ALL快,由於索引文件一般比數據文件小。
  • ALL:對於每一個來自於先前的表的行組合,進行完整的表掃描。
possible_keys

指出MySQL能使用哪一個索引在該表中找到行指針

key 顯示MySQL實際決定使用的鍵(索引)。若是沒有選擇索引,鍵是NULL。
key_len 顯示MySQL決定使用的鍵長度。若是鍵是NULL,則長度爲NULL。
ref 顯示使用哪一個列或常數與key一塊兒從表中選擇行。
rows 顯示MySQL認爲它執行查詢時必須檢查的行數。多行之間的數據相乘能夠估算要處理的行數。
filtered 顯示了經過條件過濾出的行數的百分比估計值。
Extra

該列包含MySQL解決查詢的詳細信息code

  • Distinct:MySQL發現第1個匹配行後,中止爲當前的行組合搜索更多的行。
  • Not exists:MySQL可以對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,再也不爲前面的的行組合在該表內檢查更多的行。
  • range checked for each record (index map: #):MySQL沒有發現好的可使用的索引,但發現若是來自前面的表的列值已知,可能部分索引可使用。
  • Using filesort:MySQL須要額外的一次傳遞,以找出如何按排序順序檢索行。
  • Using index:從只使用索引樹中的信息而不須要進一步搜索讀取實際的行來檢索表中的列信息。
  • Using temporary:爲了解決查詢,MySQL須要建立一個臨時表來容納結果。
  • Using where:WHERE 子句用於限制哪個行匹配下一個表或發送到客戶。
  • Using sort_union(...), Using union(...), Using intersect(...):這些函數說明如何爲index_merge聯接類型合併索引掃描。
  • Using index for group-by:相似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,能夠用來查 詢GROUP BY或DISTINCT查詢的全部列,而不要額外搜索硬盤訪問實際的表。

 

一. id

select查詢的序列號,包含一組數字,表示查詢中執行select子句或操做表的順序

id的結果共有3中狀況

1. id相同,執行順序由上至下

2. id不一樣,若是是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行

3. id相同不一樣,同時存在

 

1. id相同,執行順序由上至下 

这里写图片描述

2. id不一樣,若是是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行

这里写图片描述

3. id相同不一樣,同時存在 ,如圖,

这里写图片描述

如上圖所示,在id爲1時,table顯示的是 <derived2> ,這裏指的是指向id爲2的表,即t3表的衍生表。

 

 

 一. select_type

常見和經常使用的值有以下幾種: 

这里写图片描述

 

分別用來表示查詢的類型,主要是用於區別普通查詢、聯合查詢、子查詢等的複雜查詢。

- SIMPLE 簡單的select查詢,查詢中不包含子查詢或者UNION

- PRIMARY 查詢中若包含任何複雜的子部分,最外層查詢則被標記爲PRIMARY

- SUBQUERY 在SELECT或WHERE列表中包含了子查詢

- DERIVED 在FROM列表中包含的子查詢被標記爲DERIVED(衍生),MySQL會遞歸執行這些子查詢,把結果放在臨時表中

- UNION 若第二個SELECT出如今UNION以後,則被標記爲UNION:若UNION包含在FROM子句的子查詢中,外層SELECT將被標記爲:DERIVED

- UNION RESULT 從UNION表獲取結果的SELECT

 

1. UNION

當經過union來鏈接多個查詢結果時,第二個以後的select其select_type爲UNION。

mysql> explain select * from t_order where order_id=100 union select * from t_order where order_id=200; 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------+ 
| id | select_type  | table      | type  | possible_keys | key     | key_len | ref   | rows | Extra | 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------+ 
|  1 | PRIMARY      | t_order    | const | PRIMARY       | PRIMARY | 4       | const |    1 |       | 
|  2 | UNION        | t_order    | const | PRIMARY       | PRIMARY | 4       | const |    1 |       | 
| NULL | UNION RESULT | <union1,2> | ALL   | NULL          | NULL    | NULL    | NULL  | NULL |       | 
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-------+

 

2.DEPENDENT UNION與DEPENDENT SUBQUERY:

當union做爲子查詢時,其中第二個union的select_type就是DEPENDENT UNION。
第一個子查詢的select_type則是DEPENDENT SUBQUERY。

mysql> explain select * from t_order where order_id in (select order_id from t_order where order_id=100 union select order_id from t_order where order_id=200); 
+----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+ 
| id | select_type        | table      | type  | possible_keys | key     | key_len | ref   | rows   | Extra       | 
+----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+ 
|  1 | PRIMARY            | t_order    | ALL   | NULL          | NULL    | NULL    | NULL  | 100453 | Using where | 
|  2 | DEPENDENT SUBQUERY | t_order    | const | PRIMARY       | PRIMARY | 4       | const |      1 | Using index | 
|  3 | DEPENDENT UNION    | t_order    | const | PRIMARY       | PRIMARY | 4       | const |      1 | Using index | 
| NULL | UNION RESULT       | <union2,3> | ALL   | NULL          | NULL    | NULL    | NULL  |   NULL |             | 
+----+--------------------+------------+-------+---------------+---------+---------+-------+--------+-------------+

 

3.SUBQUERY:

子查詢中的第一個select其select_type爲SUBQUERY。

mysql> explain select * from t_order where order_id=(select order_id from t_order where order_id=100); 
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+ 
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra       | 
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+ 
|  1 | PRIMARY     | t_order | const | PRIMARY       | PRIMARY | 4       | const |    1 |             | 
|  2 | SUBQUERY    | t_order | const | PRIMARY       | PRIMARY | 4       |       |    1 | Using index | 
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+ 

4.DERIVED:

當子查詢是from子句時,其select_type爲DERIVED。

mysql> explain select * from (select order_id from t_order where order_id=100) a; 
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ 
| id | select_type | table      | type   | possible_keys | key     | key_len | ref  | rows | Extra       | 
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+ 
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL |    1 |             | 
|  2 | DERIVED     | t_order    | const  | PRIMARY       | PRIMARY | 4       |      |    1 | Using index | 
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+

 

二.type的說明

type所顯示的是查詢使用了哪一種類型,type包含的類型包括以下圖所示的幾種: 
這裏寫圖片描述

從最好到最差依次是:

system > const > eq_ref > ref > range > index > all

通常來講,得保證查詢至少達到range級別,最好能達到ref。

1.system,const

system 表只有一行記錄(等於系統表),這是const類型的特列,平時不會出現,這個也能夠忽略不計

const 表示經過索引一次就找到了,const用於比較primary key 或者unique索引。由於只匹配一行數據,因此很快。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量。

这里写图片描述

 

首先進行子查詢獲得一個結果的d1臨時表,子查詢條件爲id = 1 是常量,因此type是const,id爲1的至關於只查詢一條記錄,因此type爲system。

2.eq_ref

eq_ref 惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或惟一索引掃描

在t_order表中的order_id是主鍵,t_order_ext表中的order_id也是主鍵,該表能夠認爲是訂單表的補充信息表,他們的關係是1對1,在下面的例子中能夠看到b表的鏈接類型是eq_ref,這是極快的聯接類型。

mysql> explain select * from t_order a,t_order_ext b where a.order_id=b.order_id; 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+ 
| id | select_type | table | type   | possible_keys | key     | key_len | ref             | rows | Extra       | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+ 
|  1 | SIMPLE      | b     | ALL    | order_id      | NULL    | NULL    | NULL            |    1 |             | 
|  1 | SIMPLE      | a     | eq_ref | PRIMARY       | PRIMARY | 4       | test.b.order_id |    1 | Using where | 
+----+-------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+

3.ref

ref 非惟一性索引掃描,返回匹配某個單獨值的全部行,本質上也是一種索引訪問,它返回全部匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,因此他應該屬於查找和掃描的混合體。 

下面的例子在上面的例子上略做了修改,加上了條件。此時b表的聯接類型變成了ref。由於全部與a表中order_id=100的匹配記錄都將會從b表獲取。這是比較常見的聯接類型。

mysql> explain select * from t_order a,t_order_ext b where a.order_id=b.order_id and a.order_id=100; 
+----+-------------+-------+-------+---------------+----------+---------+-------+------+-------+ 
| id | select_type | table | type  | possible_keys | key      | key_len | ref   | rows | Extra | 
+----+-------------+-------+-------+---------------+----------+---------+-------+------+-------+ 
|  1 | SIMPLE      | a     | const | PRIMARY       | PRIMARY  | 4       | const |    1 |       | 
|  1 | SIMPLE      | b     | ref   | order_id      | order_id | 4       | const |    1 |       | 
+----+-------------+-------+-------+---------------+----------+---------+-------+------+-------+

4.ref_or_null

user_id字段是一個能夠爲空的字段,並對該字段建立了一個索引。在下面的查詢中能夠看到聯接類型爲ref_or_null,這是mysql爲含有null的字段專門作的處理。在咱們的表設計中應當儘可能避免索引字段爲NULL,由於這會額外的耗費mysql的處理時間來作優化。

mysql> explain select * from t_order where user_id=100 or user_id is null; 
+----+-------------+---------+-------------+---------------+---------+---------+-------+-------+-------------+ 
| id | select_type | table   | type        | possible_keys | key     | key_len | ref   | rows  | Extra       | 
+----+-------------+---------+-------------+---------------+---------+---------+-------+-------+-------------+ 
|  1 | SIMPLE      | t_order | ref_or_null | user_id       | user_id | 5       | const | 50325 | Using where | 
+----+-------------+---------+-------------+---------------+---------+---------+-------+-------+-------------+

5.index_merge

常常出如今使用一張表中的多個索引時。mysql會將多個索引合併在一塊兒,以下例:

mysql> explain select * from t_order where order_id=100 or user_id=10; 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+-------------------------------------------+ 
| id | select_type | table   | type        | possible_keys   | key             | key_len | ref  | rows | Extra                                     | 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+-------------------------------------------+ 
|  1 | SIMPLE      | t_order | index_merge | PRIMARY,user_id | PRIMARY,user_id | 4,5     | NULL |    2 | Using union(PRIMARY,user_id); Using where | 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+-------------------------------------------+

 

6.unique_subquery

該聯接類型用於替換value IN (SELECT primary_key FROM single_table WHERE some_expr)這樣的子查詢的ref。注意ref列,其中第二行顯示的是func,代表unique_subquery是一個函數,而不是一個普通的ref。

mysql> explain select * from t_order where order_id in (select order_id from t_order where user_id=10); 
+----+--------------------+---------+-----------------+-----------------+---------+---------+------+--------+-------------+ 
| id | select_type        | table   | type            | possible_keys   | key     | key_len | ref  | rows   | Extra       | 
+----+--------------------+---------+-----------------+-----------------+---------+---------+------+--------+-------------+ 
|  1 | PRIMARY            | t_order | ALL             | NULL            | NULL    | NULL    | NULL | 100649 | Using where | 
|  2 | DEPENDENT SUBQUERY | t_order | unique_subquery | PRIMARY,user_id | PRIMARY | 4       | func |      1 | Using where | 
+----+--------------------+---------+-----------------+-----------------+---------+---------+------+--------+-------------+

7.index_subquery

該聯接類型與上面的太像了,惟一的差異就是子查詢查的不是主鍵而是非惟一索引。

mysql> explain select * from t_order where user_id in (select user_id from t_order where order_id>10); 
+----+--------------------+---------+----------------+-----------------+---------+---------+------+--------+--------------------------+ 
| id | select_type        | table   | type           | possible_keys   | key     | key_len | ref  | rows   | Extra                    | 
+----+--------------------+---------+----------------+-----------------+---------+---------+------+--------+--------------------------+ 
|  1 | PRIMARY            | t_order | ALL            | NULL            | NULL    | NULL    | NULL | 100649 | Using where              | 
|  2 | DEPENDENT SUBQUERY | t_order | index_subquery | PRIMARY,user_id | user_id | 5       | func |  50324 | Using index; Using where | 
+----+--------------------+---------+----------------+-----------------+---------+---------+------+--------+--------------------------+

 

8.range

range 只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪一個索引,通常就是在你的where語句中出現between、< 、>、in等的查詢,這種範圍掃描索引比全表掃描要好,由於它只須要開始於索引的某一點,而結束於另外一點,不用掃描所有索引。

按指定的範圍進行檢索,很常見。

mysql> explain select * from t_order where user_id in (100,200,300); 
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+ 
| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows | Extra       | 
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+ 
|  1 | SIMPLE      | t_order | range | user_id       | user_id | 5       | NULL |    3 | Using where | 
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+

 

9.index

 

index Full Index Scan,Index與All區別爲index類型只遍歷索引樹。這一般比ALL快,由於索引文件一般比數據文件小。(也就是說雖然all和Index都是讀全表,但index是從索引中讀取的,而all是從硬盤讀取的)

在進行統計時很是常見,此聯接類型實際上會掃描索引樹,僅比ALL快些。

mysql> explain select count(*) from t_order; 
+----+-------------+---------+-------+---------------+---------+---------+------+--------+-------------+ 
| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows   | Extra       | 
+----+-------------+---------+-------+---------------+---------+---------+------+--------+-------------+ 
|  1 | SIMPLE      | t_order | index | NULL          | user_id | 5       | NULL | 100649 | Using index | 
+----+-------------+---------+-------+---------------+---------+---------+------+--------+-------------+

10.ALL

all Full Table Scan 將遍歷全表以找到匹配的行 

完整的掃描全表,最慢的聯接類型,儘量的避免。

mysql> explain select * from t_order; 
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows   | Extra | 
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+ 
|  1 | SIMPLE      | t_order | ALL  | NULL          | NULL | NULL    | NULL | 100649 |       | 
+----+-------------+---------+------+---------------+------+---------+------+--------+-------+

 

三. possible_keys 和 key

 

possible_keys 顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢實際使用

key

  • 實際使用的索引,若是爲NULL,則沒有使用索引。(可能緣由包括沒有創建索引或索引失效)
    explain select * from tb;

     

四. key_len

表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度,在不損失精確性的狀況下,長度越短越好。key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的。 

 

五. ref

顯示索引的那一列被使用了,若是可能的話,最好是一個常數。哪些列或常量被用於查找索引列上的值。 

三.extra的說明

1.Distinct

MySQL發現第1個匹配行後,中止爲當前的行組合搜索更多的行。對於此項沒有找到合適的例子,求指點。

2.Not exists

由於b表中的order_id是主鍵,不可能爲NULL,因此mysql在用a表的order_id掃描t_order表,並查找b表的行時,若是在b表發現一個匹配的行就再也不繼續掃描b了,由於b表中的order_id字段不可能爲NULL。這樣避免了對b表的屢次掃描。

mysql> explain select count(1) from t_order a left join t_order_ext b on a.order_id=b.order_id where b.order_id is null;  
+----+-------------+-------+-------+---------------+--------------+---------+-----------------+--------+--------------------------------------+ 
| id | select_type | table | type  | possible_keys | key          | key_len | ref             | rows   | Extra                                | 
+----+-------------+-------+-------+---------------+--------------+---------+-----------------+--------+--------------------------------------+ 
|  1 | SIMPLE      | a     | index | NULL          | express_type | 1       | NULL            | 100395 | Using index                          | 
|  1 | SIMPLE      | b     | ref   | order_id      | order_id     | 4       | test.a.order_id |      1 | Using where; Using index; Not exists | 
+----+-------------+-------+-------+---------------+--------------+---------+-----------------+--------+--------------------------------------+

3.Range checked for each record

這種狀況是mysql沒有發現好的索引可用,速度比沒有索引要快得多。

mysql> explain select * from t_order t, t_order_ext s where s.order_id>=t.order_id and s.order_id<=t.order_id and t.express_type>5; 
+----+-------------+-------+-------+----------------------+--------------+---------+------+------+------------------------------------------------+ 
| id | select_type | table | type  | possible_keys        | key          | key_len | ref  | rows | Extra                                          | 
+----+-------------+-------+-------+----------------------+--------------+---------+------+------+------------------------------------------------+ 
|  1 | SIMPLE      | t     | range | PRIMARY,express_type | express_type | 1       | NULL |    1 | Using where                                    | 
|  1 | SIMPLE      | s     | ALL   | order_id             | NULL         | NULL    | NULL |    1 | Range checked for each record (index map: 0x1) | 
+----+-------------+-------+-------+----------------------+--------------+---------+------+------+------------------------------------------------+

4.Using filesort

在有排序子句的狀況下很常見的一種狀況。此時mysql會根據聯接類型瀏覽全部符合條件的記錄,並保存排序關鍵字和行指針,而後排序關鍵字並按順序檢索行。

mysql> explain select * from t_order order by express_type; 
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows   | Extra          | 
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+ 
|  1 | SIMPLE      | t_order | ALL  | NULL          | NULL | NULL    | NULL | 100395 | Using filesort | 
+----+-------------+---------+------+---------------+------+---------+------+--------+----------------+

5.Using index

這是性能很高的一種狀況。當查詢所需的數據能夠直接從索引樹中檢索到時,就會出現。上面的例子中有不少這樣的例子,再也不多舉例了。

6.Using temporary

發生這種狀況通常都是須要進行優化的。mysql須要建立一張臨時表用來處理此類查詢。

mysql> explain select * from t_order a left join t_order_ext b on a.order_id=b.order_id group by b.order_id; 
+----+-------------+-------+------+---------------+----------+---------+-----------------+--------+---------------------------------+ 
| id | select_type | table | type | possible_keys | key      | key_len | ref             | rows   | Extra                           | 
+----+-------------+-------+------+---------------+----------+---------+-----------------+--------+---------------------------------+ 
|  1 | SIMPLE      | a     | ALL  | NULL          | NULL     | NULL    | NULL            | 100395 | Using temporary; Using filesort | 
|  1 | SIMPLE      | b     | ref  | order_id      | order_id | 4       | test.a.order_id |      1 |                                 | 
+----+-------------+-------+------+---------------+----------+---------+-----------------+--------+---------------------------------+

7.Using where

當有where子句時,extra都會有說明。

8.Using sort_union(...)/Using union(...)/Using intersect(...)

下面的例子中user_id是一個檢索範圍,此時mysql會使用sort_union函數來進行索引的合併。而當user_id是一個固定值時,請參看上面type說明5.index_merge的例子,此時會使用union函數進行索引合併。

mysql> explain select * from t_order where order_id=100 or user_id>10; 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+------------------------------------------------+ 
| id | select_type | table   | type        | possible_keys   | key             | key_len | ref  | rows | Extra                                          | 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+------------------------------------------------+ 
|  1 | SIMPLE      | t_order | index_merge | PRIMARY,user_id | user_id,PRIMARY | 5,4     | NULL |    2 | Using sort_union(user_id,PRIMARY); Using where | 
+----+-------------+---------+-------------+-----------------+-----------------+---------+------+------+------------------------------------------------+

對於Using intersect的例子能夠參看下例,user_id與express_type發生了索引交叉合併。

mysql> explain select * from t_order where express_type=1 and user_id=100; 
+----+-------------+---------+-------------+----------------------+----------------------+---------+------+------+----------------------------------------------------+ 
| id | select_type | table   | type        | possible_keys        | key                  | key_len | ref  | rows | Extra                                              | 
+----+-------------+---------+-------------+----------------------+----------------------+---------+------+------+----------------------------------------------------+ 
|  1 | SIMPLE      | t_order | index_merge | user_id,express_type | user_id,express_type | 5,1     | NULL |    1 | Using intersect(user_id,express_type); Using where | 
+----+-------------+---------+-------------+----------------------+----------------------+---------+------+------+----------------------------------------------------+

9.Using index for group-by

代表能夠在索引中找到分組所需的全部數據,不須要查詢實際的表。

mysql> explain select user_id from t_order group by user_id; 
+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+ 
| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows | Extra                    | 
+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+ 
|  1 | SIMPLE      | t_order | range | NULL          | user_id | 5       | NULL |    3 | Using index for group-by | 
+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+

 

除了上面的三個說明,還須要注意rows的數值,多行之間的數值是乘積的關係,能夠估算大概要處理的行數,若是乘積很大,那就頗有優化的必要了。

相關文章
相關標籤/搜索