MySQL國王的EXPLAIN

從小有一片土地叫做數據庫,數據庫上分成幾個國家:Oracle、Sybase、DB2、SQL server、Access、MySQL、BD2等等。Oracle是其中的大霸主,MySQL近年來迅速擴張,逐步在吞沒其他國家的土地。


今天我們來說說MySQL中的醫療部門--EXPLAIN。


explain主要提供select語句的執行計劃信息。select語句是叫做sql生物的其中一種,有了explain的協助可以更加方便地爲select語句體檢,根據情況判斷出該select語句的身體健康狀態。

一個優秀的select語句需要經常運動並且定期檢查,explain可以開啓慢sql檢查,對進進出出需要執行任務的sql語句進行安檢。

一份合格的體檢報告一般包含以下幾個內容:

EXPLAIN Output Columns

Column JSON Name Meaning
id select_id The SELECT identifier
select_type None The SELECT type
table table_name The table for the output row
partitions partitions The matching partitions
type access_type The join type
possible_keys possible_keys The possible indexes to choose
key key The index actually chosen
key_len key_length The length of the chosen key
ref ref The columns compared to the index
rows rows Estimate of rows to be examined
filtered filtered Percentage of rows filtered by table condition
Extra None Additional information


一般來體檢的語句分爲兩種:

① select語句自身覺得可能生病了,然後就會主動聯繫explain,把自己的身體情況詳細介紹清楚,比如select * from aa where id > 5;;

② 另外一種就是被安檢出來,你造一般情節,這類的sql語句都會東躲西藏,就算被抓到還是會吞吞吐吐,比如

select * from bb where id > 'xxx'; 完全就是負隅頑抗不想告訴你xxx是什麼。= =


檢查步驟:

1. 通過各種方式得到一個可執行的select語句。

在explain部門進行檢查之前我們必須要保證這個select語句是可執行的,既然它不想告訴我們,我們只能自己構造出一個合適的可執行的sql語句。


2. 有些select語句過於臃腫,每一個部分都被仔細檢查了一遍,得到的報告一堆又一堆,年輕人容易兩眼蚊香狀,可以拆分,部分檢查判斷部分健康狀況。

在物慾橫生的時代,臃腫並不是罕見的情況,被抓住的往往是各種聯表查詢,一層套一層的select from。


3. 關注重點指標:type、key、rows、extra

  • type值,由好到差的排序如下所示:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL


  • key:引用的索引值,可以配合possible_keys一起查看,當然possible_keys只是做參考,有時候推薦的也不一定是適用的
  • rows:

    The rows column indicates the number of rows MySQL believes it must examine to execute the query.

    這個rows就是mysql認爲必須要逐行去檢查和判斷的記錄的條數。 
    舉個例子來說,假如有一個語句 select * from t where column_a = 1 and column_b = 2;
    全表假設有100條記錄,column_a字段有索引(非聯合索引),column_b沒有索引。
    column_a = 1 的記錄有20條, column_a = 1 and column_b = 2 的記錄有5條。

    那麼最終查詢結果應該顯示5條記錄。 explain結果中的rows應該是20,因爲這20條記錄mysql引擎必須逐行檢查是否滿足where條件。

  • extra

① Using filesort

MySQL must do an extra pass to find out how to retrieve the rows in sorted order. The sort is done by going through all rows according to the join type and storing the sort key and pointer to the row for all rows that match the WHERE clause.

MYSQL需要一次額外的傳遞找到如何按照排序順序檢索行。根據連接的類型查詢所有行,爲所有匹配where語句的行存儲排序關鍵字和行指針來完成排序。

有order by語句,但是索引加得不得當 → 對sql語句和索引進行優化,但並不是說出現了using filesort就需要優化,主要判斷標準在於是否影響到性能。
題外話:

聯合索引: 
key ('A1','A2','A3','A4'),排序的思路一般是,先按照A1來排序,A1相同,然後按照A2排序,以此類推,這樣對於(A1), (A1, A2), (A1, A2, A3)的索引都是有效的,但是對於(A2, A3)這樣的索引就無效了。

② Using where:表示優化器需要通過索引回表查詢數據;
③ Using index:表示直接訪問索引就足夠獲取到所需要的數據,不需要通過索引回表;
④ Using index condition:在5.6版本後加入的新特性(Index Condition Pushdown);

Q1. What's the difference between "Using index condition" and "Using where;Using index" in the EXPLAIN?

Q2. Which is better?

Using index condition : where condition contains indexed and non-indexed column and the optimizer will first resolve the indexed column and will look for the rows in the table for the other condition (index push down)

Using where; Using index : 'Using index' meaning not doing the scan of entire table. 'Using where' may still do the table scan on non-indexed column but it will use if there is any indexed column in the where condition first more like using index condition

Which is better? 'Using where; Using index' would be better then 'Using index condition' if query has index all covering.

Q3. What's the difference between "Using index" and "Using where;Using index" in the EXPLAIN?


這個問題相對簡單一點,可以參考:http://stackoverflow.com/questions/25672552/whats-the-difference-between-using-index-and-using-where-using-index-in-the

Q4. 爲什麼EXPLAIN SELECT customer_id FROM rental WHERE customer_id>=300;會使用索引,而 EXPLAIN SELECT * FROM rental WHERE customer_id>=300; 則不會使用索引呢?


優化器會在索引存在的情況下,通過符合 RANGE 範圍的條數和總數的比例來選擇是使用索引還是進行全表遍歷。
當需要讀取的數據超過一個臨界值時,優化器會放棄從索引中讀取而改爲進行全表掃描,這是爲了避免過多的 random disk。


4. 根據體檢報告對sql語句進行合適的建議,優化後再次體檢,共同奔向社會主義和諧社會。


注意:explain只能做建議,不能完全依靠。


好了,我編不下去了。

參考資料如下所示:

http://dev.mysql.com/doc/refman/5.7/en/explain-output.html

除了該鏈接外還參考了http://stackoverflow.com/questions上的一些問題以及答案,比較淺薄地介紹一下,歡迎指摘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章