mysql explain用法

explain顯示了mysql如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。
使用方法,在select語句前加上explain就能夠了,如:mysql

explain select * from statuses_status where id=11;

建立測試表:sql

CREATE TABLE people( id int auto_increment primary key, zipcode char(32) not null default '', address varchar(128) not null default '', lastname char(64) not null default '', firstname char(64) not null default '', birthdate char(10) not null default '' ); CREATE TABLE people_car( people_id int, plate_number varchar(16) not null default '', engine_number varchar(16) not null default '', lasttime timestamp );

 插入測試數據:服務器

insert into people (zipcode,address,lastname,firstname,birthdate) values ('230031','anhui','zhan','jindong','1989-09-15'), ('100000','beijing','zhang','san','1987-03-11'), ('200000','shanghai','wang','wu','1988-08-25') insert into people_car (people_id,plate_number,engine_number,lasttime) values (1,'A121311','12121313','2013-11-23 :21:12:21'), (2,'B121311','1S121313','2011-11-23 :21:12:21'), (3,'C121311','1211SAS1','2012-11-23 :21:12:21')

 建立索引用來測試測試

alter table people add index(zipcode,firstname,lastname);

 explain介紹優化

先從一個最簡單的查詢開始:ui

Query-1 explain select zipcode,firstname,lastname from people;

 explain輸出結果共有id,select_type,table,type,possible_keys,key,key_len,ref,rows和Extra幾列。每一列分別表明什麼意思呢,請看下面的解釋。spa

select_type 表示查詢中每一個select語句的類型(簡單 OR複雜),能夠有下面幾種code

a.SIMPLE:最簡單的SELECT查詢,沒有使用UNION或子查詢,見Query-1。blog

b.PRIMARY:在嵌套的查詢中是最外層的SELECT語句,在UNION查詢中是最前面的SELECT語句。見Query-2和Query-3。排序

                    查詢中若包含任何複雜的子部分,最外層查詢則被標記爲:PRIMARY

Query-2 explain select zipcode from (select * from people a) b;

Query-3 explain select * from people where zipcode = 100000 union select * from people where zipcode = 200000;

c.UNION:UNION中第二個以及後面的SELECT語句。見Query-3。

d.DERIVED:派生表SELECT語句中FROM子句中的SELECT語句。見Query-2。

e.UNION RESULT:一個UNION查詢的結果。見Query-3。

f.DEPENDENT UNION:顧名思義,首先須要知足UNION的條件,及UNION中第二個以及後面的SELECT語句,同時該語句依賴外部的查詢。

Query-4 explain select * from people where id in (select id from people where zipcode = 100000 union select id from people where zipcode = 200000 );

g.SUBQUERY:子查詢中第一個SELECT語句。

Query-6 explain select * from people where id = (select id from people where zipcode = 100000);

table :顯示的這一行信息是關於哪一張表的。有時候並非真正的表名。

Query-7 explain select * from (select * from (select * from people a) b ) c;

能夠看到若是指定了別名就顯示的別名。
<derivedN>N就是id值,指該id值對應的那一步操做的結果。
還有<unionM,N>這種類型,出如今UNION語句中,見Query-4。
注意:MySQL對待這些表和普通表同樣,可是這些「臨時表」是沒有任何索引的。

type
type列很重要,是用來講明表與表之間是如何進行關聯操做的,有沒有使用索引。MySQL中「關聯」一詞比通常意義上的要寬泛,MySQL認爲任何一次查詢都是一次「關聯」,並不只僅是一個查詢須要兩張表才叫關聯,因此也能夠理解MySQL是如何訪問表的。主要有下面幾種類別。

const

當肯定最多隻會有一行匹配的時候,MySQL優化器會在查詢前讀取它並且只讀取一次,所以很是快。const只會用在將常量和主鍵或惟一索引進行比較時,並且是比較全部的索引字段。people表在id上有一個主鍵索引,在(zipcode,firstname,lastname)有一個二級索引。所以Query-8的type是const而Query-9並非:

Query-8 explain select * from people where id=1;

Query-9 explain select * from people where zipcode = 100000;

注意下面的Query-10也不能使用const table,雖然也是主鍵,也只會返回一條結果。

Query-10 explain select * from people where id >2;

system
這是const鏈接類型的一種特例,表僅有一行知足條件。

Query-11 explain select * from (select * from people where id = 1 )b;

<derived2>已是一個const table而且只有一條記錄。

eq_ref

惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。 常見於主鍵或惟一索引掃描。eq_ref類型是除了const外最好的鏈接類型。
建立員工表Employee和經理表Manager

create table Employee ( ID int auto_increment, Ename varchar(32), Age int, Salary float, MID int, Primary key (ID) ); create table Manager ( MID int, Name varchar(32), Primary key(MID) );
Query-12 explain select * from Employee A,Manager B where A.MID=B.MID;

MID對於表Manager是惟一的,主鍵索引,來與employee鏈接,故type爲eq_ref。

ref

非惟一性索引掃描,返回匹配某個單獨值的全部行。常見於使用非惟一索引即惟一索引的非惟一前綴進行的查找。
這個類型跟eq_ref不一樣的是,它用在關聯操做只使用了索引的最左前綴,或者索引不是UNIQUE和PRIMARY KEY。ref能夠用於使用=或<=>操做符的帶索引的列。

Query-13 explain select * from people where zipcode='100000';

 

zipcode、firstname和lastname組成索引,這裏只使用了name,即只使用了惟一性索引的一部分,故爲ref。

fulltext
連接是使用全文索引進行的。通常咱們用到的索引都是B樹,這裏就不舉例說明了。
ref_or_null
該類型和ref相似。可是MySQL會作一個額外的搜索包含NULL列的操做。在解決子查詢中常用該聯接類型的優化。

range

只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪一個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列爲NULL。當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操做符,用常量比較關鍵字列時,可使用range。

索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行, 常見於between、<、>,IN等的查詢。

Query-14 explain select * from people where id=1 or id=2;

Query-15 explain select * from people where id>1;

Query-16 explain select * from people where id in (1,2);

index
該聯接類型與ALL相同,除了只有索引樹被掃描。這一般比ALL快,由於索引文件一般比數據文件小。這個類型一般的做用是告訴咱們查詢是否使用索引進行排序操做。

按索引掃描表,雖然仍是全表掃描,但優勢是索引是有序的。index與ALL區別爲index類型只遍歷索引樹。

Query-17 explain select * from people order by id;

ALL
最慢的一種方式,即全表掃描。

總結

explain的type列從最差到最好依次是:
ALL:全表掃描。
index:索引掃描。
range:索引範圍掃描。
ref :非惟一性索引掃描。
eq_ref :惟一性索引掃描。
const,system:將查詢轉換爲一個常量。
null:MySQL在優化過程當中分解語句,執行時甚至不用訪問表或索引

possible_keys
possible_keys列指出MySQL能使用哪一個索引在該表中找到行。查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用。

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

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

ref
ref列顯示使用哪一個列或常數與key一塊兒從表中選擇行。
表示上述表的鏈接匹配條件,即哪些列或常量被用於查找索引列上的值。

rows
rows列顯示MySQL認爲它執行查詢時必須檢查的行數。注意這是一個預估值。

Extra
Extra是EXPLAIN輸出中另一個很重要的列,該列顯示MySQL在查詢過程當中的一些詳細信息,包含的信息不少,只選擇幾個重點的介紹下。

Using filesort
MySQL有兩種方式能夠生成有序的結果,經過排序操做或者使用索引,當Extra中出現了Using filesort 說明MySQL使用了後者,但注意雖然叫filesort但並非說明就是用了文件來進行排序,只要可能排序都是在內存裏完成的。大部分狀況下利用索引排序更快,因此通常這時也要考慮優化查詢了。

Using temporary
說明使用了臨時表,通常看到它說明查詢須要優化了,就算避免不了臨時表的使用也要儘可能避免硬盤臨時表的使用。

Not exists
MYSQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行, 就再也不搜索了。

Using index
說明查詢是覆蓋了索引的,這是好事情。MySQL直接從索引中過濾不須要的記錄並返回命中的結果。這是MySQL服務層完成的,但無需再回表查詢記錄。

Using index condition
這是MySQL 5.6出來的新特性,叫作「索引條件推送」。簡單說一點就是MySQL原來在索引上是不能執行如like這樣的操做的,可是如今能夠了,這樣減小了沒必要要的IO操做,可是隻能用在二級索引上。

Using where
使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。

注意:Extra列出現Using where表示MySQL服務器將存儲引擎返回服務層之後再應用WHERE條件過濾。

相關文章
相關標籤/搜索