MySQL 執行計劃說明

上一篇文章“SQL關聯查詢 直接join 和子查詢的區別”中提到了explain,即執行計劃。執行計劃是數據庫引擎的重要一環,今天針對explain結果瞭解下,順便提及幾個有意思的話題,如“回表”、“如何在MySQL中實現rowNum”。

explain結果說明

MySQL 執行計劃說明

  • select_type
類型 說明
SIMPLE 簡單SELECT(不使用UNION或子查詢等)
PRIMARY 主查詢,即最外面的SELECT
UNION UNION中的第二個或後面的SELECT語句
DEPENDENT UNION NION中的第二個或後面的SELECT語句,取決於外面的查詢
UNION RESULT UNION的結果
SUBQUERY 子查詢中的第一個SELECT
DEPENDENT SUBQUERY 子查詢中的第一個SELECT,取決於外面的查詢
SUBQUERY 導出表的SELECT(FROM子句的子查詢)
  • table
    輸出結果集的表名

  • partitions
    存在分區時,使用到哪些分區

  • type
    連接使用了哪種類別,有無使用索引,是使用Explain命令分析性能瓶頸的關鍵項之一。常見訪問類型如下,按照性能排序,從上到下,從差到好。一般來說,得保證查詢至少達到range級別,最好能達到ref,否則就可能會出現性能問題。
類型 示例說明
ALL 全表掃描 一般是沒有where條件或者where條件沒有使用索引的查詢語句
index 索引全掃描 一般是查詢的字段都有索引的查詢語句
range 索引範圍掃描 常用於<、<=、>、>=、between等操作
ref 非唯一索引掃描 使用非唯一索引或唯一索引的前綴掃描,返回匹配某個單獨值的記錄行
eq_ref 唯一索引掃描 類似ref,區別在於使用的索引是唯一索引,對於每個索引鍵值,表中只有一條記錄匹配
const,system 單表最多有一個匹配行 onst/system出現在根據主鍵primary key或者 唯一索引 unique index 進行的查詢
NULL 不用掃描表或索引 select 1 from dual
  • possible_keys
    列指出MySQL能使用哪個索引在該表中找到行

  • key
    顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL

  • key_len
    顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度爲NULL。使用的索引的長度。在不損失精確性的情況下,長度越短越好

  • ref
    顯示使用哪個列或常數與key一起從表中選擇行。

  • rows
    顯示MySQL認爲它執行查詢時必須檢查的行數。

  • filtered
    存儲引擎返回的數據在server層過濾後,剩下多少滿足查詢的記錄數量的比例(百分比)

  • extra
    包含MySQL解決查詢的詳細信息,也是關鍵參考項之一。
extra元素 說明
Distinct 一旦MYSQL找到了與行相聯合匹配的行,就不再搜索了
Not exists MYSQL 優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜索了
Range checked for each
Record 沒有找到理想的索引,因此對於從前面表中來的每一 個行組合,MYSQL檢查使用哪個索引,並用它來從表中返回行。這是使用索引的最慢的連接之一
Using filesort 表示MySQL需額外排序操作, 不能通過索引順序達到排序效果
Using index 表示索引覆蓋,不會回表查詢
Using temporary 通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上
Using where 表示進行了回表查詢

什麼是回表

簡單來說就是數據庫根據索引找到了指定的記錄所在行後,還需要根據rowid再次到數據塊裏取數據的操作。比如這樣的執行計劃,先索引掃描,再通過rowid去取索引中未能提供的數據,即爲回表。“回表”一般就是指執行計劃裏顯示的“TABLE ACCESS BY INDEX ROWID”。再例如,雖然只查詢索引裏的列,但是需要回表過濾掉其他行。

怎麼避免回表?
將需要的字段放在索引中去。查詢的時候就能避免回表。但是不要刻意去避免回表,那樣代價太了。也不是將所有的字段都放在所有中。

回表和MySQL的索引實現有關係,有興趣的朋友可以進一步瞭解B+樹相關原理,參照下面這篇文章“從B樹、B+樹、B*樹談到R 樹”。

MySQL如何獲取rownum

不同於oracle的rownum,mysql不太直接提供這樣的字段,但是可以用變量的方法添加僞自增序列,語法格式爲
SELECT @rownum:=@rownum+1 AS rownum, table_name.* FROM (SELECT @rownum:=0) r, table_name ;

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