引言
日常工作中,使用MySQL的機會還是蠻多的,主要考慮Schema與數據類型優(yōu)化、如何創(chuàng)建索引、根據業(yè)務場景的查詢優(yōu)化。這些想必大家都在高性能MySQL這本書中看過,可能也比作者理解的深,本文旨在對EXPLAIN語句使用、分析進行整理。
EXPLAIN語句是什么?
官網對于EXPLAIN的作用定義如下:
The EXPLAIN statement provides information about how MySQL executes statements. EXPLAIN works with SELECT, DELETE, INSERT, REPLACE, and UPDATE statements.
簡單來講,EXPLAIN語句告訴我們MySQL如何執(zhí)行SQL語句,而我們通過這些信息,可以達到優(yōu)化SQL語句執(zhí)行效率的目的。
接下來,就要對EXPLAIN返回的格式進行了解了,具體如下:
| 字段名 | 字段描述 |
|---|---|
| id | 查詢語句內SELECT的序列號 |
| select_type | SELECT類型 |
| table | 訪問的表名 |
| partitions | 命中分區(qū) |
| type | 數據訪問類型,下文詳細介紹 |
| possible_keys | 有關索引,實際情況可能不可用 |
| key | MySQL查詢優(yōu)化器實際使用的索引 |
| key_len | 索引存儲長度 |
| ref | 實際使用的索引中,用于比較的常量或列 |
| rows | 查詢需要讀取的行數,innodb引擎是一個衡量效率的指標,有時可能不準確 |
| Extra | 查詢執(zhí)行的附加信息,下文詳細介紹 |
在分析SQL語句執(zhí)行時,主要用到的列,分別為
type、Extra,下文的測試用例均為官網提供的sakila數據庫,附上下載鏈接。本文使用MySQL 8.0.12、Navicat 12.1
type列主要出現值(性能從好到差)
- system:表只有一行,const類型的特殊情況。
- const:查詢結果最多有一行,多為主鍵、唯一索引與常量比較的情況。
explain select * from actor where actor_id = 1
- eq_ref:一種特殊的索引查找,MySQL知道最多只返回一條符合條件的記錄,使用主鍵、NOT NULL的唯一索引會看到(用navicat發(fā)現結果也是ref)。
explain select * from actor, film_actor where actor.actor_id = film_actor.actor_id and actor.actor_id = 1
- ref:一種索引查找,返回所有匹配某個單個值的行,然而,可能會找到多個符合條件的行,當使用非唯一性索引或者唯一性索引的非唯一性前綴時發(fā)生。
explain select * from film where title= 'ACE GOLDFINGER'
- range:范圍掃描就是一個有限制的索引掃描, 不用遍歷所有索引,例如索引在
BETWEEN、>、>范圍內的。
explain select * from film where film_id BETWEEN 1 AND 100
- index:全表掃描,只是MySQL掃描表時按索引次序而不是行。
Extra列中看到“Using index”,說明是覆蓋索引,只需要讀取索引列,不需要讀取行數據。
使用索引次序全表讀取。
explain select actor.actor_id from film_actor, actor where film_actor.actor_id = actor.actor_id
- ALL:全表掃描,讀取行數據,找到需要的行。
explain select * from film_actor, actor where film_actor.actor_id = actor.actor_id
Extra列主要出現的值
- Using index:使用覆蓋索引,避免回表查詢行數據。
- Using where:存儲引擎檢索行后再進行過濾。
- Using temporary:對查詢結果排序時會使用一個臨時表,盡量避免使用臨時表。
- Using filesort:對結果使用一個外部索引排序,而不是按索引次序從表里讀取行,需要進行優(yōu)化。
總結
由于查詢優(yōu)化器的存在,實際運行查詢語句會和想的不一致,因此在進行查詢語句優(yōu)化時,最好運行下EXPLAIN語句,看看是不是和自己想的一致。