Mysql查看執行計劃-explain

author:skate
time:2012/02/17
 
Mysql查看執行計劃
 
 
一.語法
 
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 |                          |
+—-+——————–+————+——–+——————-+———+———+——-+——+————————–+
 
(4).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_table
WHERE 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                        | key_len | ref  | rows | Extra                                                |
+—-+————-+——-+————-+—————————-+—————————-+———+——+——+——————————————————+
|  1 | SIMPLE      | t4    | index_merge | idx_t4_id,idx_t4_accountid | idx_t4_id,idx_t4_accountid | 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
 <br /

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *