Mysql索引分析

這裏主要利用explain來觀察語句是否走索引。html

explain語法自行百度,詳見Mysql官方文檔。mysql

1、explain輸出格式說明sql

具體說明:數據庫

1) id緩存

該字段標識select語句id,若SQL中只有1個select語句(即便是多表關聯查詢),則該值爲1,不然依次遞增;若SQL是union的結果,則該值爲NULL。優化

2) select_type網站

該字段說明select語句的類型,其可能的取值以下圖(來自官網文檔):spa

其中,simple是最多見的類型,代表SQL只包含1個select語句;derived代表該行表明的數據表(derived table)實際上是from子句中包含的子查詢的輸出結果;其他類型較易理解,閱讀官方文檔便可,這裏不贅述。翻譯

3) tablehtm

該字段代表explain輸出的每行所表明的數據集來自哪張表,其值一般是具體的表名,當數據集是union的結果時,其值可能

是<unionM,N>,當數據集來自derived table時,其值多是<derivedN>。這裏提到的M或N均是id字段的值。

4) type

該字段代表各表是如何被join的,其取值比較複雜,詳細可參考官網文檔。這裏只列出最多見的幾種取值。

a. system/const

const代表上述"table"字段表明的數據集中,最多隻有1行記錄命中本步執行計劃的查詢條件,例如這步執行計劃的sql的where

子句以某張表的primary key或unique index與常數作比較時,該執行計劃對應的type字段取值就是const。

system只是const值的一個特例,它表示本步執行計劃要操做的數據集中只有1行記錄。

它們只可能出如今單表查詢SQL的type字段取值中。

b. eq_ref

該值代表本步執行計劃操做的數據集中關聯字段是索引字段且只有1條記錄符合上步執行計劃操做的數據集的關聯條件。

是對多表作關聯查詢時,可能獲得的最優的join類型(由於它一般代表關聯的字段是本步執行計劃要操做的表的primary key或unique index)。

c. ref

該值代表本步執行計劃操做的數據集中關聯字段是索引字段但不僅有1條記錄符合上步執行計劃操做的數據集的關聯條件。

符合關聯條件的記錄不僅1條代表關聯字段非primary key或unique index,當符合關聯條件的記錄數比較少時,這種join_type='ref'的場景仍是比較合理的,但它顯然不如join_type='eq_ref'高效。

d. ref_or_null

該join type類型與ref的場景相似,但它代表MySQL會對包含NULL值的字段作額外搜索。例以下面SQL的join type就是ref_or_null:

SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;

e. index_merge

該值代表MySQL會對本步執行計劃進行index merge優化,觸發index merge的SQL一般包含'or'操做,常見實例以下:

SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;

SELECT * FROM tbl_name WHERE (key1 = 10 OR key2 = 20) AND non_key=30;

SELECT * FROM t1, t2 WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%') AND t2.key1=t1.some_col;

SELECT * FROM t1, t2 WHERE t1.key1=1 AND (t2.key1=t1.some_col OR t2.key2=t1.some_col2);

f. range

該值代表本步執行計劃只操做單表且符合查詢條件的記錄不僅1,可能出如今有in或between操做的SQL中。

只限於單表操做場景也是其與前面提到的join_type取值爲'ref'場景的區別,由於ref可能出如今單表/多表join操做場景下。

g. ALL

該值代表本步執行計劃會對數據集作全表掃描,這是必須作優化的場景。一般能夠經過對某些字段合理建索引來避免全表掃描。

h. index

該值代表MySQL執行本步計劃時掃描的是index tree,而ALL則是掃全表。它可能在兩種場景下出現:

case1. 本步計劃查詢數據集時select語句須要返回的字段是該數據集索引字段的最左前綴匹配集。如table A中已創建含2個字段的聯合索引(f1, f2),則select f1 from A where f2 = 'yyy'可能會觸發MySQL掃描index tree,這種狀況下,執行計劃的Extra字段會包含"Using index"來代表它掃描的是index tree,由於f1是(f1, f2)最終前綴匹配集中的1個元素;而select f2 from A where f2 = 'yyy'則會掃描全表。

case2. 本步計劃按照索引順序進行全表掃描來查找符合條件的數據。這種狀況下,執行計劃的Extra字段不會包含"Using index",這種全表掃描也是必須優化的場景。

5) possible_keys

該字段的值是可能被MySQL用做索引的字段,若值爲NULL,則沒有字段會被用做索引,所以查詢效率不會高,這種狀況下,須要優化數據表的索引結構。

6) key

該字段的值是MySQL真正用到的索引。

值得注意的是:該字段的值有可能不是possible_keys列出的候選索引字段,例如,當前查詢SQL要返回的字段是數據表某索引字段的最左前綴匹配字段,但SQL的where條件中沒有使用數據表的索引字段,則此時possible_keys可能爲NULL,而key字段的值多是那個能cover住待查詢字段的數據表索引字段,此時,MySQL會掃描索引樹,雖然低效,但比起掃描全表仍是要快。這種場景也正是本文前面解釋join_type='index'時提到的case1。

此外,在select語句中藉助"force index或"use index"能夠強制MySQL使用possible_keys中列出的候選索引字段。

7) key_len

該字段的值代表上述key字段的length,當MySQL將某聯合索引字段做爲SQL執行時用到的索引時,key_len字段能夠暗示MySQL真正在什麼程度上(多長的最左前綴匹配字段)使用了該聯合索引。若key字段的值爲NULL,則key_len字段值也爲NULL。

8) ref

該字段的值代表數據表中的哪列或哪一個constants會被用於與key字段指定的索引作比較。

9) rows

該字段的值代表MySQL執行該步計劃對應的query時必須掃描的行數。這個值對於SQL優化很是具備參考意義,一般狀況下,該值越小查詢效率越高。

10) Extra

該字段的值包含了MySQL執行query時的其它額外信息。該字段可能的取值狀況較多,詳細狀況可參考官網文檔的說明。

該說明官網均有,既然有現成本身也就懶得翻譯了。

PS:

字段說明參考網址:http://www.2cto.com/database/201502/377682.html

Mysql官方網址:http://dev.mysql.com/doc/refman/5.5/en/explain-output.html

2、其餘問題

show index返回的字段意思:

1)     Table 表的名稱。

2)     Non_unique 若是索引不能包括重複詞,則爲0,若是能夠則爲1。

3)     Key_name 索引的名稱

4)     Seq_in_index 索引中的列序列號,從1開始。

5)     Column_name 列名稱。

6)     Collation 列以什麼方式存儲在索引中。在MySQL中,有值‘A’(升序)或NULL(無分類)。

7)     Cardinality 索引中惟一值的數目的估計值。經過運行ANALYZE TABLE或myisamchk -a能夠更新。基數根據被存儲爲整數的統計數據來計數,因此即便對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL使用該索引的機會就越大。

8)     Sub_part 若是列只是被部分地編入索引,則爲被編入索引的字符的數目。若是整列被編入索引,則爲NULL。

9)     Packed 指示關鍵字如何被壓縮。若是沒有被壓縮,則爲NULL。

10)   Null 若是列含有NULL,則含有YES。若是沒有,則該列含有NO。

11)   Index_type 用過的索引方法(BTREE, FULLTEXT, HASH, RTREE)。

12)   Comment 多種評註,您可使用db_name.tbl_name做爲tbl_name FROM db_name語法的另外一種形式。這兩個語句是等價的:

mysql>SHOW INDEX FROM mytable FROM mydb;

mysql>SHOW INDEX FROM mydb.mytable;

 

http://www.th7.cn/db/mysql/201508/114301.shtml

SELECT /*!40001 SQL_NO_CACHE */ * FROM ... :

1 /*! */ 這是mysql 特里的語法,並不是註釋,由於裏面達到條件也會執行。

2 !後面是版本號, 若是本數據庫等於或大於此版本號,那麼註釋內的代碼也會執行。

3 那麼這句話的意思是 若是版本號大於或等於4,會執行 sql_no_cache, 就是不用緩存數據。 而並不是說本次查詢不做爲下次查詢的緩存。

4 在備份操做時Mysql 會自動調用此語法。

 

3、實踐操做

本身項目就不展現了,安利一個網站。

推薦網址:http://tech.meituan.com/mysql-index.html(美團團隊Mysql慢查詢分析與解析,裏面還詳細講了數據庫使用的B+樹)

相關文章
相關標籤/搜索