mysql優化之explain備忘筆記

      今天使用explain來查看sql執行狀況的時候發現有的東西忘掉了,故做此篇文章來強化此知識點的記憶。mysql

1.explain做用sql

exlain 執行結果顯示了mysql 存儲引擎如何使用索引來處理select語句,可以幫助咱們寫出效率更高的sql語句,發揮mysql那些被埋沒的能力。其實update語句也可使用explainlai查看其使用狀況,須要作的就是將update語句改成select就能夠了,後面的條件不變。由於update修改一條記錄時也是要先找到這條記錄的,故能夠替換update爲select來用explain查看尋找數據時使用索引的狀況。函數

2.使用方式性能

在select語句前加上explain就能夠了。好比 explain select * from user where uanme="dd";優化

3.使用實例spa

 

mysql> explain select log_id,login_time from stat.stat_user_login_log order by login_time;
+----+-------------+---------------------+-------+---------------+------------+---------+------+------+-------------+
| id | select_type | table               | type  | possible_keys | key        | key_len | ref  | rows | Extra       |
+----+-------------+---------------------+-------+---------------+------------+---------+------+------+-------------+
|  1 | SIMPLE      | stat_user_login_log | index | NULL          | login_time | 4       | NULL |   32 | Using index |
+----+-------------+---------------------+-------+---------------+------------+---------+------+------+-------------+
1 row in set (0.00 sec)

 

4.結果詳解指針

第一列  id  :select 識別符 select 的查詢序列號code

第二列  select_type:select類型 能夠爲如下任何一種:blog

  simple:普通的select,不使用多表連接(union) 或子查詢排序

  primary:最外面的select

  union:union中的第二個或者後面的select

  dependent subquery:子查詢中的第一個select,取決於外面的查詢

  derived:導出表的select(from子句的子查詢)

第三列 table:輸出的行所引用的表

第四列 type:聯接類型,下面給出各類聯接類型,按照從最佳類型到最壞類型進行排序

  system:表中僅有一行。這是const鏈接類型的一個特例

  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

  eq_ref:對於每一個來自於前面的表的行組合,從該表中讀取一行。這多是最好的聯接類型,除了const類型。它用在一個索引的全部部分被聯接使用而且索引是UNIQUEPRIMARY 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 ef_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

   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

 

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;

  index_merge:該聯接類型表示使用了索引合併優化方法。在這種狀況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。

      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:只檢索給定範圍的行,使用一個索引來選擇行。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);

  index:該聯接類型與ALL相同,除了只有索引樹被掃描。這一般比ALL快,由於索引文件一般比數據文件小。

當查詢只使用做爲單索引一部分的列時,MySQL可使用該聯接類型。

  ALL:對於每一個來自於先前的表的行組合,進行完整的表掃描。若是表是第一個沒標記const的表,這一般很差,而且一般在它狀況下差。一般能夠增長更多的索引而不要使用ALL,使得行能基於前面的表中的常數值或列值被檢索出。

第五列 possible_keys:possible_keys列指出MySQL能使用哪一個索引在該表中找到行。注意,該列徹底獨立於EXPLAIN輸出所示的表的次序。這意味着在possible_keys中的某些鍵實際上不能按生成的表次序使用。

若是該列是NULL,則沒有相關的索引。在這種狀況下,能夠經過檢查WHERE子句看是否它引用某些列或適合索引的列來提升你的查詢性能。若是是這樣,創造一個適當的索引而且再次用EXPLAIN檢查查詢。

爲了看清一張表有什麼索引,使用SHOW INDEX FROM tbl_name

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

 

第七列    key_len:key_len列顯示MySQL決定使用的鍵長度。若是鍵是NULL,則長度爲NULL。注意經過key_len值咱們能夠肯定MySQL將實際使用一個多部關鍵字的幾個部分。

第八列    ref:ref列顯示使用哪一個列或常數與key一塊兒從表中選擇行。

第九列    rows:rows列顯示MySQL認爲它執行查詢時必須檢查的行數。

第十列    Extra:該列包含MySQL解決查詢的詳細信息。下面解釋了該列能夠顯示的不一樣的文本字符串:

       Distinct:MySQL發現第1個匹配行後,中止爲當前的行組合搜索更多的行。

       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中的行。若是MySQLt2中發現一個匹配的行,它知道t2.id毫不會爲NULL,而且再也不掃描t2內有相同的id值的行。換句話說,對於t1的每一個行,MySQL只須要在t2中查找一次,不管t2內實際有多少匹配的行。

     range checked for each record :MySQL沒有發現好的可使用的索引,但發現若是來自前面的表的列值已知,可能部分索引可使用。對前面的表的每一個行組合,MySQL檢查是否可使用range或index_merge訪問方法來索取行。

這並不很快,但比執行沒有索引的聯接要快得多。

       Using filesort:MySQL須要額外的一次傳遞,以找出如何按排序順序檢索行。經過根據聯接類型瀏覽全部行併爲全部匹配WHERE子句的行保存排序關鍵字和行的指針來完成排序。而後關鍵字被排序,並按排序順序檢索行。

        Using index:從只使用索引樹中的信息而不須要進一步搜索讀取實際的行來檢索表中的列信息。當查詢只使用做爲單一索引一部分的列時,可使用該策略。

       Using temporary:爲了解決查詢,MySQL須要建立一個臨時表來容納結果。典型狀況如查詢包含能夠按不一樣狀況列出列的GROUP BY和ORDER BY子句時。

      Using where:WHERE子句用於限制哪個行匹配下一個表或發送到客戶。除非你專門從表中索取或檢查全部行,若是Extra值不爲Using where而且表聯接類型爲ALL或index,查詢可能會有一些錯誤。

若是想要使查詢儘量快,應找出Using filesort Using temporaryExtra值。

        Using sort_union(...)Using union(...)Using intersect(...)

這些函數說明如何爲index_merge聯接類型合併索引掃描。

      Using index for group-by:相似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,能夠用來查詢GROUP BYDISTINCT查詢的全部列,而不要額外搜索硬盤訪問實際的表。而且,按最有效的方式使用索引,以便對於每一個組,只讀取少許索引條目。

相關文章
相關標籤/搜索