EXPLAIN語句能夠用做DESCRIBE的一個同義詞,或得到關於MySQL如何執行SELECT語句的信息:EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name的一個同義詞。html
· 若是在SELECT語句前放上關鍵詞EXPLAIN,MySQL將解釋它如何處理SELECT,提供有關表如何聯接和聯接的次序。mysql
藉助於EXPLAIN,能夠知道何時必須爲表加入索引以獲得一個使用索引來尋找記錄的更快的SELECT。還能夠知道優化器是否以一個最佳次序聯接表。爲了強制優化器讓一個SELECT語句按照表命名順序的聯接次序,語句應以STRAIGHT_JOIN而不僅是SELECT開頭。算法
查看執行計劃,能夠分析SQL合理地使用存在的索引,或調整當前的索引。sql
語法:服務器
explain <sql語句> 或者 explain [extended] <sql語句> 或 explain partitions <sql語句>函數
EXPLAIN爲用於SELECT語句中的每一個表返回一行信息。表以它們在處理查詢過程當中將被MySQL讀入的順序被列出。MySQL用一遍掃描屢次聯接(single-sweep multi-join)的方式解決全部聯接。這意味着MySQL從第一個表中讀一行,而後找到在第二個表中的一個匹配行,而後在第3個表中等等。當全部的表處理完後,它輸出選中的列而且返回表清單直到找到一個有更多的匹配行的表。從該表讀入下一行並繼續處理下一個表。性能
當使用EXTENDED關鍵字時,EXPLAIN產生附加信息,用於將執行計劃‘反編譯’成SQL語句,運行show warnings 可等到優化後的查詢語句,包括優化器限定SELECT語句中的表和列名,重寫而且執行優化規則後SELECT語句是什麼樣子,而且還可能包括優化過程的其它註解。 優化
Partitions用於分區表的執行計劃。server
注:也可使用desc命令來查看執行計劃,用法desc <sql語句>htm
mysql> explain select * from order_item;
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | order_item | ALL | NULL | NULL | NULL | NULL | 4553 | |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
mysql> desc select * from order_item;
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | order_item | ALL | NULL | NULL | NULL | NULL | 4553 | |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.02 sec)
EXPLAIN的每一個輸出行提供一個表的相關信息,而且每一個行包括下面的列:
• id SELECT識別符。這是SELECT的查詢序列號。
例:
mysql> explain select * from (select * from (select * from tb where id = 4) 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 | tb | const | PRIMARY | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
3 rows in set (0.59 sec)
這條SQL的執行順序是從裏向外的執行,就是從id=3 向上執行。說明:對於子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
mysql> explain select s.id, s.sname from student s, sc, course c where s.id=sc.sid and sc.cid = c.id and c.tid = '1001';
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
| 1 | SIMPLE | s | ALL | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | sc | ref | sid,cid | sid | 5 | testdb.s.id | 1 | Using where |
| 1 | SIMPLE | c | eq_ref | PRIMARY,tid | PRIMARY | 4 | testdb.sc.cid | 1 | Using where |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
3 rows in set (0.00 sec)
這條SQL的執行順序是從左到右,說明:id相同時,執行順序由上至下
id若是相同,能夠認爲是一組,從上往下順序執行;在全部組中,id值越大,優先級越高,越先執行
• select_type SELECT類型,能夠爲如下任何一種:
o SIMPLE 簡單SELECT(不含UNION或子查詢)
o PRIMARY 子查詢中的最外層查詢,(不是主鍵查詢)
o UNION UNION中的第二個或後面的SELECT語句(第一個SELECT 爲PRIMARY)
o DEPENDENT UNION UNION中的第二個或後面的SELECT語句,取決於外面的查詢
o UNION RESULT UNION的結果。
o SUBQUERY 子查詢中的第一個SELECT,結果不依賴於外部查詢結果集;
o DEPENDENT SUBQUERY 子查詢中的第一個SELECT,取決於外面的查詢
o DERIVED 導出表的SELECT(FROM子句的子查詢)
• table 輸出的行所引用的表。
• type 聯接類型,表示MySQL在表中找到所需行的方式,又稱「訪問類型」。下面給出各類聯接類型,按照從最佳類型到最壞類型進行排序:
常見類型以下:
由左至右,性能由最差到最好
o NULL MySQL在優化過程當中分解語句,執行時甚至不用訪問表域索引。
o system 表僅有一行(=系統表)。這是const聯接類型的一個特例。
o 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 student where id=1001;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | student | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
主鍵位於Where列表中,MySQL將該查詢轉換爲一個常量。例:
或mysql> explain select * from (select * from student where id=1001) t;
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | student | const | PRIMARY | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
2 rows in set (0.00 sec)
o eq_ref (惟一性索引掃描) 最多隻會有一條匹配結果,通常是經過主鍵或者惟一鍵索引來訪問; 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> explain select * from teacher t, teacher t1 where t.id = t1.id; --惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或惟一索引掃描
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------+
| 1 | SIMPLE | t | ALL | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | testdb.t.id | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------+
2 rows in set (0.00 sec)
o ref (非惟一性索引掃描) 返回匹配某個單獨值的全部行,常見於使用非惟一索引或惟一索引的非惟一前綴進行的查找
Join 語句中被驅動表索引引用查詢:對於每一個來自於前面的表的行組合,全部有匹配索引值的行將從這張表中讀取。若是聯接只使用鍵的最左邊的前綴,或若是鍵不是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> select * from teacher t, course c where t.id=c.tid;
+------+-------+------+---------+------+
| id | tname | id | cname | tid |
+------+-------+------+---------+------+
| 2010 | wang | 1011 | english | 2010 |
+------+-------+------+---------+------+
1 row in set (0.00 sec)
mysql>
mysql> explain select * from teacher t, course c where t.id=c.tid; --非惟一性索引掃描,返回匹配某個單獨值的全部行。常見於使用非惟一索引即惟一索引的非惟一前綴進行的查找
+----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+
| 1 | SIMPLE | t | ALL | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | c | ref | tid | tid | 5 | testdb.t.id | 1 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+
2 rows in set (0.00 sec)
o ref_or_null 該聯接類型如同ref,可是添加了MySQL能夠專門搜索包含NULL值的行。在解決子查詢中常用該聯接類型的優化。與ref 惟一區別就是在使用索引引用查詢以外再增長一個空值的查詢;參見7.2.7節,「MySQL如何優化IS NULL」。
例:在下面的例子中,MySQL可使用ref_or_null聯接來處理ref_tables:
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
o index_merge 查詢中同時使用兩個(或更多)索引,而後對索引結果進行merge 以後再讀取表數據。在這種狀況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。詳細信息參見7.2.6節,「索引合併優化」。
o unique_subquery 子查詢中的返回結果字段組合是主鍵或者惟一約束。該類型替換了下面形式的IN子查詢的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一個索引查找函數,能夠徹底替換子查詢,效率更高。
o index_subquery 子查詢中的返回結果字段組合是一個索引(或索引組合),但不是一個主鍵或者惟一索引。該聯接類型相似於unique_subquery,能夠替換IN子查詢,但只適合下列形式的子查詢中的非惟一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
o range (索引範圍掃描) :只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪一個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列爲NULL。當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操做符,用常量比較關鍵字列時,可使用range:
例: SELECT * FROM tbl_name WHERE key_column = 10;
SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20;
SELECT * FROM tbl_name WHERE key_column IN (10,20,30);
SELECT * FROM tbl_name WHERE key_part1= 10 AND key_part2 IN (10,20,30);
例:
mysql> explain select * from course where tid between 2000 and 3000; --索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行,常見於between、<、>等的查詢
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | course | range | tid | tid | 5 | NULL | 1 | Using where |
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
注意,在對主鍵使用between 或in 等查詢時,也多是:
mysql> explain select * from teacher where id between 2000 and 3000;
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | PRIMARY | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> explain select * from teacher where id in (2000, 3000);
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | PRIMARY | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
o index (全索引掃描) :該聯接類型與ALL相同,除了只有索引樹被掃描。這一般比ALL快,由於索引文件一般比數據文件小。當查詢只使用做爲單索引一部分的列時,MySQL可使用該聯接類型。
o ALL (全表掃描):對於每一個來自於先前的表的行組合,進行完整的表掃描。若是表是第一個沒標記const的表,這一般很差,而且一般在它狀況下不好。一般能夠增長更多的索引而不要使用ALL,使得行能基於前面的表中的常數值或列值被檢索出。
• possible_keys 該查詢能夠利用的索引。 若是沒有任何索引可使用,就會顯示成null,在這種狀況下,能夠經過檢查WHERE子句看是否它引用某些列或適合索引的列來提升你的查詢性能。若是是這樣,創造一個適當的索引而且再次用EXPLAIN檢查查詢。參見13.1.2節,「ALTER TABLE語法」。
爲了看清一張表有什麼索引,使用SHOW INDEX FROM tbl_name。
• key key列顯示MySQL實際從possible_keys 中所選擇使用的鍵(索引)。若是沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。參見13.2.7節,「SELECT語法」。
對於MyISAM和BDB表,運行ANALYZE TABLE能夠幫助優化器選擇更好的索引。對於MyISAM表,可使用myisamchk --analyze。參見13.5.2.1節,「ANALYZE TABLE語法」和5.9.4節,「表維護和崩潰恢復」。
• key_len 被選中使用索引的索引鍵長度。若是鍵是NULL,則長度爲NULL。注意經過key_len值咱們能夠肯定MySQL將實際使用一個多部關鍵字的幾個部分。
例:
mysql> explain select cname from course; -- 沒有利用到索引
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | course | ALL | NULL | NULL | NULL | NULL |1 | |
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
mysql> explain select * from course where tid = 2002; -- 這裏存在一個外鍵索引
+----+-------------+--------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | course | ref | tid | tid | 5 | const | 1 | Using where |
+----+-------------+--------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的
• ref 列出是經過常量(const),仍是某個表的某個字段(若是是join)來過濾(經過key)的;
例:
mysql> explain select * from teacher t, course c where t.id=c.tid and c.cname='ac';
+----+-------------+-------+-------+---------------+-------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+-------------+------+-------------+
| 1 | SIMPLE | t | index | PRIMARY | tname | 43 | NULL | 1 | Using index |
| 1 | SIMPLE | c | ref | tid | tid | 5 | testdb.t.id | 1 | Using where |
+----+-------------+-------+-------+---------------+-------+---------+-------------+------+-------------+
2 rows in set (0.00 sec)
本例中,由key_len可知course表的tid被充分使用,course表的tid匹配teacher表的id,course表的cname匹配’ac’。
• rows rows列顯示MySQL認爲它執行查詢時必須檢查的行數。
• Extra 該列包含MySQL解決查詢的詳細信息。下面解釋了該列能夠顯示的不一樣的文本字符串:
o Distinct MySQL找到了第一條匹配的結果後,將中止該值的查詢而轉爲後面其餘值的查詢;
o Not exists MySQL可以對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,再也不爲前面的的行組合在該表內檢查更多的行。
下面是一個能夠這樣優化的查詢類型的例子:
SELECT * 從t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
假定t2.id定義爲NOT NULL。在這種狀況下,MySQL使用t1.id的值掃描t1並查找t2中的行。若是MySQL在t2中發現一個匹配的行,它知道t2.id毫不會爲NULL,而且再也不掃描t2內有相同的id值的行。換句話說,對於t1的每一個行,MySQL只須要在t2中查找一次,不管t2內實際有多少匹配的行。
o range checked for each record (index map: #) MySQL沒有發現好的可使用的索引,但發現若是來自前面的表的列值已知,可能部分索引可使用。對前面的表的每一個行組合,MySQL檢查是否可使用range或index_merge訪問方法來索取行。關於適用性標準的描述參見7.2.5節,「範圍優化」和7.2.6節,「索引合併優化」,不一樣的是前面表的全部列值已知而且認爲是常量。這並不很快,但比執行沒有索引的聯接要快得多。
o Using filesort(使用文件排序) 當Query 中包含ORDER BY 操做,並且沒法利用索引完成排序操做的時候,MySQL Query Optimizer 不得不選擇相應的排序算法(文件排序)來實現。參見7.2.12節,「MySQL如何優化ORDER BY」。
o Using index(使用索引排序) 所須要的數據只須要在Index 便可所有得到而不須要再到表中取數據。當查詢只使用做爲單一索引一部分的列時,可使用該策略。
例:
mysql> explain select * from teacher where tname like 'tom';
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | tname | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
若是是mysql> explain select id, tname from teacher where tname like 'tom';
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | tname | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
覆蓋索引(Covering Index):MySQL能夠利用索引返回select列表中的字段,而沒必要根據索引再次讀取數據文件,包含全部知足查詢須要的數據的索引稱爲 覆蓋索引(Covering Index)
注意: 若是要使用覆蓋索引,必定要注意select列表中只取出須要的列,不可select *,由於若是將全部字段一塊兒作索引會致使索引文件過大,查詢性能降低。
o Using temporary(使用臨時表) 當MySQL 在某些操做中必須使用臨時表的時候(使用臨時表來存儲結果集),在Extra 信息中就會出現Using temporary 。主要常見於GROUP BY 和ORDER BY (分組與排序)等操做中。
mysql> explain select * from course where id in (1000, 3000) group by cname;
+----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------+
| 1 | SIMPLE | course | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where; Using temporary; Using filesort |
+----+-------------+--------+-------+---------------+---------+---------+------+------+---------------------------------+
1 row in set (0.00 sec)
注意的是,若是cname上存在索引,則結果就不同了,如,在teacher表的tname存在惟一約束,故:
mysql> explain select * from teacher where id in (2000, 3000) group by tname;
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | PRIMARY | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
o Using where (使用子句過濾) 若是不是讀取表的全部數據,或者不是僅僅經過索引就能夠獲取全部須要的數據,則會出現Using where 信息。若是想要使查詢儘量快,應找出Using filesort 和Using temporary的Extra值。
若是查詢未能使用索引,Using where的做用只是提醒咱們MySQL將用where子句來過濾結果集
mysql> explain select * from course where cname like 'english';
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | course | ALL | NULL | NULL | NULL | NULL |1 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
o Using sort_union(...), Using union(...), Using intersect(...) 這些函數說明如何爲index_merge聯接類型合併索引掃描。詳細信息參見7.2.6節,「索引合併優化」。
o Using index for group-by 相似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,能夠用來查詢GROUP BY或DISTINCT查詢的全部列,而不要額外搜索硬盤訪問實際的表。而且,按最有效的方式使用索引,以便對於每一個組,只讀取少許索引條目。詳情參見7.2.13節,「MySQL如何優化GROUP BY」。
經過相乘EXPLAIN輸出的rows列的全部值,你能獲得一個關於一個聯接如何的提示。這應該粗略地告訴你MySQL必須檢查多少行以執行查詢。當你使用max_join_size變量限制查詢時,也用這個乘積來肯定執行哪一個多表SELECT語句。參見7.5.2節,「調節服務器參數」。
MySQL執行計劃的侷限
• EXPLAIN不會告訴你關於觸發器、存儲過程的信息或用戶自定義函數對查詢的影響狀況
• EXPLAIN不考慮各類Cache
• EXPLAIN不能顯示MySQL在執行查詢時所做的優化工做
• 部分統計信息是估算的,並不是精確值
• EXPALIN只能解釋SELECT操做,其餘操做要重寫爲SELECT後查看執行計劃
相關表:
mysql> show create table student\G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL DEFAULT '0',
`sname` varchar(20) DEFAULT NULL,
`sex` varchar(2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> show create table course\G;
*************************** 1. row ***************************
Table: course
Create Table: CREATE TABLE `course` (
`id` int(11) NOT NULL DEFAULT '0',
`cname` varchar(20) DEFAULT NULL,
`tid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `tid` (`tid`),
CONSTRAINT `course_ibfk_1` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> show create table sc\G;
*************************** 1. row ***************************
Table: sc
Create Table: CREATE TABLE `sc` (
`sid` int(11) DEFAULT NULL,
`cid` int(11) DEFAULT NULL,
`score` int(11) DEFAULT NULL,
KEY `sid` (`sid`),
KEY `cid` (`cid`),
CONSTRAINT `sc_ibfk_1` FOREIGN KEY (`sid`) REFERENCES `student` (`id`),
CONSTRAINT `sc_ibfk_2` FOREIGN KEY (`cid`) REFERENCES `course` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> show create table teacher\G;
*************************** 1. row ***************************
Table: teacher
Create Table: CREATE TABLE `teacher` (
`id` int(11) NOT NULL DEFAULT '0',
`tname` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `tname` (`tname`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> alter table teacher add unique(tname);
insert into teacher values(2010, 'wang');
insert into course values(1011, 'english', 2010);