SQL夯實基礎(六):MqSql Explain

來源:互聯網
上載者:User

標籤:tor   應該   inf   pos   where   col   編碼   span   customer   

  關係型資料庫中,互連網相關行業使用最多的無疑是mysql,雖然我們C# Developer很多用的都是sql server ,但是學習一些mysql方面的知識也是必要的,他山之石麼。

  先上一個explain的執行個體,以下我會通過我自己的理解,逐個解釋表中每列的含義。(僅供樣本使用,實際項目不建議如此寫sql)。

id

  這個欄位是用來確定查詢語句執行的優先順序的。

這個值會有三種情況:

id值相同:這種情況意味著查詢語句按照explain結果中的id自上而下執行

id值不相同:這種情況下,id值會自遞增,id值越大,explain結果中的相應sql語句被執行的優先順序越高,越先被執行。這通常會在子查詢中出現

id值存在相同的和不同的值:這種情況下,id值越大,優先順序越高,越先被執行,那麼,對於id值相同的結果,mysql會按照explain結果中的id自上而下執行。

select_type

表示查詢的類型,先看錶

 

PRIMARY:查詢中若包含若干子查詢或者巢狀查詢,那麼最外層的查詢將被標記為PRIMARY.

SUBQUERY:在select或where語句中包含子查詢

DERIVED:在from列表中包含的子查詢將被標記為DERIVED(衍生),MySQL會遞迴執行這些子查詢,將結果放在暫存資料表中。

table

對應行正在訪問哪一個表,表名或者別名,有可能是一下幾種

1 實際的表名  

2 表的別名

比如 select * from customer as c

3 derived  子查詢

<derivedx>, x是個數字,我的理解是第幾步執行的結果

4 null 直接結算的結果,不走表

關聯最佳化器會為查詢選擇關聯順序,左側深度優先

當from中有子查詢的時候,表名是derivedN的形式,N指向子查詢,也就是explain結果中的下一列

當有union result的時候,表名是union 1,2等的形式,1,2表示參與union的query id

注意:MySQL對待這些表和普通表一樣,但是這些“暫存資料表”是沒有任何索引的。

 

type:

type顯示的是訪問類型,是較為重要的一個指標,結果值從好到壞依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般來說,得保證查詢至少達到range層級,最好能達到ref。

 

ref            使用非唯一索引掃描或唯一索引首碼掃描(有時候需要索引很長的字元列,這會讓索引變得大且慢。通常可以索引開始的部分字元,這樣可以大大節約索引空間,從而提高索引效率),返回單條記錄,常出現在關聯查詢中

eq_ref         類似ref,區別在於使用的是唯一索引,使用主鍵的關聯查詢

possible_keys

  指出MySQL能使用哪個索引在表中找到記錄,查詢涉及到的欄位上若存在索引,則該索引將被列出,但不一定被查詢使用

  該列完全獨立於EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實際上不能按產生的表次序使用。

  如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查WHERE子句看是否它引用某些列或適合索引的列來提高你的查詢效能。如果是這樣,創造一個適當的索引並且再次用EXPLAIN檢查查詢

 

key

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

key_len

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

表示查詢最佳化工具使用了索引的位元組數. 這個欄位可以評估複合式索引是否完全被使用, 或只有最左部分欄位被使用到.

key_len 的計算規則如下:

字串

char(n): n 位元組長度

varchar(n): 如果是 utf8 編碼, 則是 3 n + 2位元組; 如果是 utf8mb4 編碼, 則是 4 n + 2 位元組.

數實值型別:

TINYINT: 1位元組

SMALLINT: 2位元組

MEDIUMINT: 3位元組

INT: 4位元組

BIGINT: 8位元組

時間類型

DATE: 3位元組

TIMESTAMP: 4位元組

DATETIME: 8位元組

欄位屬性: NULL 屬性 佔用一個位元組. 如果一個欄位是 NOT NULL 的, 則沒有此屬性.

我們來舉兩個簡單的栗子:
mysql> EXPLAIN SELECT * FROM order_info WHERE user_id < 3 AND product_name = ‘p1‘ AND productor = ‘WHH‘ \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: order_info   partitions: NULL         type: rangepossible_keys: user_product_detail_index          key: user_product_detail_index      key_len: 9          ref: NULL         rows: 5     filtered: 11.11        Extra: Using where; Using index1 row in set, 1 warning (0.00 sec)

上面的例子是從表 order_info 中查詢指定的內容, 而我們從此表的建表語句中可以知道, 表 order_info 有一個聯合索引:

KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`)

不過此查詢語句 WHERE user_id < 3 AND product_name = ‘p1‘ AND productor = ‘WHH‘ 中, 因為先進行 user_id 的範圍查詢, 而根據 最左首碼匹配 原則, 當遇到範圍查詢時, 就停止索引的匹配, 因此實際上我們使用到的索引的欄位只有 user_id, 因此在 EXPLAIN 中, 顯示的 key_len 為 9. 因為 user_id 欄位是 BIGINT, 佔用 8 位元組, 而 NULL 屬性佔用一個位元組, 因此總共是 9 個位元組. 若我們將user_id 欄位改為 BIGINT(20) NOT NULL DEFAULT ‘0‘, 則 key_length 應該是8.

上面因為 最左首碼匹配 原則, 我們的查詢僅僅使用到了聯合索引的 user_id 欄位, 因此效率不算高.

 

接下來我們來看一下下一個例子:

mysql> EXPLAIN SELECT * FROM order_info WHERE user_id = 1 AND product_name = ‘p1‘ \G;*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: order_info   partitions: NULL         type: refpossible_keys: user_product_detail_index          key: user_product_detail_index      key_len: 161          ref: const,const         rows: 2     filtered: 100.00        Extra: Using index1 row in set, 1 warning (0.00 sec)

       這次的查詢中, 我們沒有使用到範圍查詢, key_len 的值為 161. 為什麼呢? 因為我們的查詢條件 WHERE user_id = 1 AND product_name = ‘p1‘ 中, 僅僅使用到了聯合索引中的前兩個欄位, 因此 keyLen(user_id) + keyLen(product_name) = 9 + 50 * 3 + 2 = 161

rows

rows 也是一個重要的欄位. MySQL 查詢最佳化工具根據統計資訊, 估算 SQL 要尋找到結果集需要掃描讀取的資料行數.

這個值非常直觀顯示 SQL 的效率好壞, 原則上 rows 越少越好.

Extra

EXplain 中的很多額外的資訊會在 Extra 欄位顯示, 常見的有以下幾種內容:

 

Using join buffer:改值強調了在擷取串連條件時沒有使用索引,並且需要串連緩衝區來儲存中間結果。如果出現了這個值,那應該注意,根據查詢的具體情況可能需要添加索引來改進能。

總結:

• EXPLAIN不會告訴你關於觸發器、預存程序的資訊或使用者自訂函數對查詢的影響情況

• EXPLAIN不考慮各種Cache

• EXPLAIN不能顯示MySQL在執行查詢時所作的最佳化工作

• 部分統計資訊是估算的,並非精確值

• EXPALIN只能解釋SELECT操作,其他動作要重寫為SELECT後查看執行計畫。

 

SQL夯實基礎(六):MqSql Explain

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.