1. 程式人生 > >MySQL 執行計劃說明

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:[email protected]+1 AS rownum, table_name.* FROM (SELECT @rownum:=0) r, table_name ;