【轉】MySQL執行計畫分析

來源:互聯網
上載者:User

標籤:

一.文法
explain <sql語句>
例如: explain select * from t3 where id=3952602;

二.explain輸出解釋

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

1.id

  SQL執行順序的標識,SQL從大到小的執行.
  例如:

mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       ||  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       ||  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

很顯然這條SQL是從裡向外的執行,就是從id=3 向上執行.

 

2. select_type
  就是select類型,可以有以下幾種

(1) SIMPLE
  簡單SELECT(不使用UNION或子查詢等) 例如:

mysql> explain select * from t3 where id=3952602;+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+|  1 | SIMPLE      | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

 

(2). PRIMARY

  最外層的select.例如:

mysql> explain select * from (select * from t3 where id=3952602) 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     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

 

(3).UNION

  UNION中的第二個或後面的SELECT語句.例如

mysql> explain select * from t3 where id=3952602 union all select * from t3 ;+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+| id | select_type  | table      | type  | possible_keys     | key     | key_len | ref   | rows | Extra |+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+|  1 | PRIMARY      | t3         | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       ||  2 | UNION        | t3         | ALL   | NULL              | NULL    | NULL    | NULL  | 1000 |       ||NULL | UNION RESULT | <union1,2> | ALL   | NULL              | NULL    | NULL    | NULL  | NULL |      |+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+

 

(4).DEPENDENT UNION

  UNION中的第二個或後面的SELECT語句,取決於外面的查詢

mysql> explain select * from t3 where id in (select id from t3 where id=3952602 union all select id from t3)  ;+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+| id | select_type        | table      | type   | possible_keys     | key     | key_len | ref   | rows | Extra                    |+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+|  1 | PRIMARY            | t3         | ALL    | NULL              | NULL    | NULL    | NULL  | 1000 | Using where              ||  2 | DEPENDENT SUBQUERY | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              ||  3 | DEPENDENT UNION    | t3         | eq_ref | PRIMARY,idx_t3_id | PRIMARY | 4       | func  |    1 | Using where; Using index ||NULL | UNION RESULT       | <union2,3> | ALL    | NULL              | NULL    | NULL    | NULL  | NULL |                         |+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+

 

(5).UNION RESULT


  UNION的結果。

mysql> explain select * from t3 where id=3952602 union all select * from t3 ;+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+| id | select_type  | table      | type  | possible_keys     | key     | key_len | ref   | rows | Extra |+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+|  1 | PRIMARY      | t3         | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       ||  2 | UNION        | t3         | ALL   | NULL              | NULL    | NULL    | NULL  | 1000 |       ||NULL | UNION RESULT | <union1,2> | ALL   | NULL              | NULL    | NULL    | NULL  | NULL |      |+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+

 



(5).SUBQUERY

  子查詢中的第一個SELECT.

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

 

(6). DEPENDENT SUBQUERY

  子查詢中的第一個SELECT,取決於外面的查詢

mysql> explain select id from t3 where id in (select id from t3 where id=3952602 )  ;+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+| id | select_type        | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra                    |+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+|  1 | PRIMARY            | t3    | index | NULL              | PRIMARY | 4       | NULL  | 1000 | Using where; Using index ||  2 | DEPENDENT SUBQUERY | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              |+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+

 


(7).DERIVED

  派生表的SELECT(FROM子句的子查詢)

mysql> explain select * from (select * from t3 where id=3952602) 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     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

 

3.table

  顯示這一行的資料是關於哪張表的.
  有時不是真實的表名字,看到的是derivedx(x是個數字,我的理解是第幾步執行的結果)

mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       ||  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       ||  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

 

4.type

  這列很重要,顯示了串連使用了哪種類別,有無使用索引.
  從最好到最差的連線類型為const、eq_reg、ref、range、indexhe和ALL

(1).system

  這是const聯結類型的一個特例。表僅有一行滿足條件.如下(t3表上的id是primary key)

mysql> explain select * from (select * from t3 where id=3952602) 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     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

 

(2).const

  表最多有一個匹配行,它將在查詢開始時被讀取。因為僅有一行,在這行的列值可被最佳化器剩餘部分認為是常數。const表很快,因為它們唯讀取一次!

  const用於用常數值比較PRIMARY KEY或UNIQUE索引的所有部分時。在下面的查詢中,tbl_name可以用於const表:
  SELECT * from tbl_name WHERE primary_key=1;
  SELECT * from tbl_name WHERE primary_key_part1=1和primary_key_part2=2;

  例如:

mysql> explain select * from t3 where id=3952602;+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows | Extra |+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+|  1 | SIMPLE      | t3    | const | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 |       |+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+

 


(3). eq_ref

  對於每個來自於前面的表的行組合,從該表中讀取一行。這可能是最好的聯結類型,除了const類型。它用在一個索引的所有部分被聯結使用並且索引是UNIQUE或PRIMARY KEY。

  eq_ref可以用於使用= 操作符比較的帶索引的列。比較值可以為常量或一個使用在該表前面所讀取的表的列的運算式。

  在下面的例子中,MySQL可以使用eq_ref聯結來處理ref_tables:

SELECT * FROM ref_table,other_table  WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table  WHERE ref_table.key_column_part1=other_table.column    AND ref_table.key_column_part2=1;

 



例如

mysql> create unique index  idx_t3_id on t3(id) ;Query OK, 1000 rows affected (0.03 sec)Records: 1000  Duplicates: 0  Warnings: 0 mysql> explain select * from t3,t4 where t3.id=t4.accountid;+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+| id | select_type | table | type   | possible_keys     | key       | key_len | ref                  | rows | Extra |+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+|  1 | SIMPLE      | t4    | ALL    | NULL              | NULL      | NULL    | NULL                 | 1000 |       ||  1 | SIMPLE      | t3    | eq_ref | PRIMARY,idx_t3_id | idx_t3_id | 4       | dbatest.t4.accountid |    1 |       |+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+

 



(4).ref

  對於每個來自於前面的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯結只使用鍵的最左邊的首碼,或如果鍵不是UNIQUE或PRIMARY KEY(換句話說,如果聯結不能基於關鍵字選擇單個行的話),則使用ref。如果使用的鍵僅僅匹配少量行,該聯結類型是不錯的。

  ref可以用於使用=或<=>操作符的帶索引的列。

  在下面的例子中,MySQL可以使用ref聯結來處理ref_tables:

SELECT * FROM ref_table WHERE key_column=expr; SELECT * FROM ref_table,other_table  WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table  WHERE ref_table.key_column_part1=other_table.column    AND ref_table.key_column_part2=1;

 



例如:

mysql> drop index idx_t3_id on t3;Query OK, 1000 rows affected (0.03 sec)Records: 1000  Duplicates: 0  Warnings: 0 mysql> create index idx_t3_id on t3(id) ;Query OK, 1000 rows affected (0.04 sec)Records: 1000  Duplicates: 0  Warnings: 0 mysql> explain select * from t3,t4 where t3.id=t4.accountid;+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+| id | select_type | table | type | possible_keys     | key       | key_len | ref                  | rows | Extra |+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+|  1 | SIMPLE      | t4    | ALL  | NULL              | NULL      | NULL    | NULL                 | 1000 |       ||  1 | SIMPLE      | t3    | ref  | PRIMARY,idx_t3_id | idx_t3_id | 4       | dbatest.t4.accountid |    1 |       |+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+2 rows in set (0.00 sec)

 



(5). ref_or_null

  該聯結類型如同ref,但是添加了MySQL可以專門搜尋包含NULL值的行。在解決子查詢中經常使用該聯結類型的最佳化。

  在下面的例子中,MySQL可以使用ref_or_null聯結來處理ref_tables:

SELECT * FROM ref_tableWHERE key_column=expr OR key_column IS NULL;

 



(6). index_merge

  該聯結類型表示使用了索引合并最佳化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。

  例如:

mysql> explain select * from t4 where id=3952602 or accountid=31754306 ;+----+-------------+-------+-------------+----------------------------+----------------------------+| id | select_type | table | type        | possible_keys              | key                        |+----+-------------+-------+-------------+----------------------------+----------------------------+|  1 | SIMPLE      | t4    | index_merge | idx_t4_id,idx_t4_accountid | idx_t4_id,idx_t4_accountid |+----+-------------+-------+-------------+----------------------------+----------------------------++---------+------+------+------------------------------------------------------+| key_len | ref  | rows | Extra                                                |+---------+------+------+------------------------------------------------------+| 4,4     | NULL |    2 | Using union(idx_t4_id,idx_t4_accountid); Using where |+---------+------+------+------------------------------------------------------+1 row in set (0.00 sec)

 

(7). unique_subquery

  該類型替換了下面形式的IN子查詢的ref:

  value IN (SELECT primary_key FROM single_table WHERE some_expr)
  unique_subquery是一個索引尋找函數,可以完全替換子查詢,效率更高。

(8).index_subquery

  該聯結類型類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:

  value IN (SELECT key_column FROM single_table WHERE some_expr)

(9).range

  只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列為NULL。

  當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比較關鍵字列時,可以使用range

mysql> explain select * from t3 where id=3952602 or id=3952603 ;+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+| id | select_type | table | type  | possible_keys     | key       | key_len | ref  | rows | Extra       |+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+|  1 | SIMPLE      | t3    | range | PRIMARY,idx_t3_id | idx_t3_id | 4       | NULL |    2 | Using where |+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+1 row in set (0.02 sec)

 



(10).index

  該聯結類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引檔案通常比資料檔案小。

  當查詢只使用作為單索引一部分的列時,MySQL可以使用該聯結類型。

(11). ALL

  對於每個來自於先前的表的行組合,進行完整的表掃描。如果表是第一個沒標記const的表,這通常不好,並且通常在它情況下很差。通常可以增加更多的索引而不要使用ALL,使得行能基於前面的表中的常數值或列值被檢索出。


5.possible_keys

  possible_keys列指出MySQL能使用哪個索引在該表中找到行。注意,該列完全獨立於EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實際上不能按產生的表次序使用。

  如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查WHERE子句看是否它引用某些列或適合索引的列來提高你的查詢效能。如果是這樣,創造一個適當的索引並且再次用EXPLAIN檢查查詢

6. key

  key列顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

7.key_len

  key_len列顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。
  使用的索引的長度。在不損失精確性的情況下,長度越短越好

8. ref

  ref列顯示使用哪個列或常數與key一起從表中選擇行。

9. rows

  rows列顯示MySQL認為它執行查詢時必須檢查的行數。

10. Extra

  該列包含MySQL解決查詢的詳細資料,下面詳細.

(1).Distinct
  一旦MYSQL找到了與行相聯合匹配的行,就不再搜尋了

(2).Not exists
  MYSQL最佳化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜尋了

(3).Range checked for each

  Record(index map:#)
  沒有找到理想的索引,因此對於從前面表中來的每一個行組合,MYSQL檢查使用哪個索引,並用它來從表中返回行。這是使用索引的最慢的串連之一

(4).Using filesort www.2cto.com
  看到這個的時候,查詢就需要最佳化了。MYSQL需要進行額外的步驟來發現如何對返回的行排序。它根據連線類型以及儲存排序索引值和匹配條件的全部行的行指標來排序全部行

(5).Using index
  列資料是從僅僅使用了索引中的資訊而沒有讀取實際的行動的表返回的,這發生在對錶的全部的請求列都是同一個索引的部分的時候

(6).Using temporary
  看到這個的時候,查詢需要最佳化了。這裡,MYSQL需要建立一個暫存資料表來儲存結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上

(7).Using where
  使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給使用者。如果不想返回表中的全部行,並且連線類型ALL或index,這就會發生,

【轉】MySQL執行計畫分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.