1. 程式人生 > >Explain 檢測SQL語句的效能

Explain 檢測SQL語句的效能

     做系統如果不封裝底層的話,就需要拼寫一大串的SQL語句,但是你對你出來的sql語句效能有多少了解呢?

exlain關鍵字來檢測一下你所拼寫的sql語句效能吧,當你看到結果的時候希望你不要被自己辛辛苦苦拼寫出來的sql語句嚇到.

下面來看看根據專案要求,我拼寫的一個sql語句:

select ta.boothNumber, ta.tenantId,ta.purchaseCount,ta.purchaseTime,ta.category,ta.name,ta.tenantName ,ta.idCardNumber,ta.factoryName,ta.ttnstartFactoryCode,ta.ttnendFactoryCode  from (
select t5.*,tt2.*  from (
select t4.*,ttn.startFactoryCode as ttnstartFactoryCode ,ttn.endFactoryCode as ttnendFactoryCode  from (
select t2.*,tm.name,tm.contactName,tm.contactPhone,tm.controllerName from (
select t1.boothNumber,t1.tenantId,t1.purchaseCount,t1.purchaseTime ,t1.boothId,t1.marketId,t1.category ,t1.id,te.permitNo,te.tenantName,te.idCardNumber   from(select tb.boothNumber,tb.tenantId,tp.purchaseCount,tp.purchaseTime ,tp.boothId,tp.marketId,tp.category ,tp.id from t_tenant_purchaseinfo tp
  INNER JOIN t_booth tb on tp.boothId =tb.id ) t1 
 INNER JOIN t_tenant te on t1.tenantId=te.tenantId  ) t2 ,(
select * from t_market) tm where t2.marketId=tm.marketId  )t4 ,(
select * from t_tenant_ticket_number) ttn where ttn.tenantpurchaseinfoId=t4.id )t5, (
select tt1.*,ftn.startFactoryCode as ftnstartFactoryCode,ftn.endFactoryCode as ftnendFactoryCode from (
select e.entranceId,e.marketId as emarketId,  e.produceDate,e.productNum, e.storage,f.factoryName from t_entrance e 
INNER JOIN t_factoryinfo  f on e.factoryId=f.factoryId )tt1,(
select * from t_factory_ticket_number ) ftn where tt1.entranceId=ftn.entranceId )tt2 where t5.marketId=tt2.emarketId and t5.ttnstartFactoryCode>=tt2.ftnstartFactoryCode and t5.ttnendFactoryCode <= ftnendFactoryCode)ta

這個sql語句涉及的表比較多,explain來看看這條語句的效能,其結果如下:

看到這個結果你肯定很迷茫,想要了解,就先了解列名所代表的的含義:

Id:MySQL QueryOptimizer 選定的執行計劃中查詢的序列號。表示查詢中執行 select 子句或操作表的順序,id 值越大優先順序越高,越先被執行。id 相同,執行順序由上至下。

Select_type一共有9中型別,只介紹常用的4:

SIMPLE: 簡單的 select 查詢,不使用 union 及子查詢

PRIMARY: 最外層的 select 查詢

UNION: UNION 中的第二個或隨後的 select 查詢,依賴於外部查詢的結果集

DERIVED: 用於 from 子句裡有子查詢的情況。 MySQL 遞迴執行這些子查詢, 把結果放在臨時表裡。

Table:輸出行所引用的表

Type:從有到差的順序如下:

System-->const-->eq_ref-->ref-->ref_or_null-->index_merge-->unique_subquery-->index_subquery-->range-->index-->all.

各自的含義如下:

system:  表僅有一行(=系統表)。這是 const 連線型別的一個特例。

const:  const

用於用常數值比較 PRIMARY KEY 時。當查詢的表僅有一行時,使用 System

eq_ref: 從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用

ref:  連線不能基於關鍵字選擇單個行,可能查詢到多個符合條件的行。叫做 ref 是因為索引要跟某個參考值相比較。這個參考值或者是一個常數,或者是來自一個表裡的多表查詢的結果值。

ref_or_null:  如同 ref, 但是 MySQL 必須在初次查詢的結果裡找出 null 條目,然後進行二次查詢。

index_merge: 說明索引合併優化被使用了。

unique_subquery:  在某些 IN 查詢中使用此種類型,而不是常規的 ref:valueIN (SELECT primary_key FROM single_table WHERE some_expr)

index_subquery:  IN 使 , unique_subquery 類似,但是查詢的是非唯一性索引

range:  只檢索給定範圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引。當使用= <>>>=<<=IS NULL<=>BETWEEN 或者 IN 操作符,用常量比較關鍵字列時,以使用 range

index:  全表掃描,只是掃描表的時候按照索引次序進行而不是行。主要優點就是避免了排序, 但是開銷仍然非常大。

all: 最壞的情況,從頭到尾全表掃描。

possible_keys : 指出能在該表中使用哪些索引有助於查詢。如果為空,說明沒有可用的索引。

key:實際從 possible_key 選擇使用的索引。如果為 NULL,則沒有使用索引。很少的情況,MYSQL 會選擇優化不足的索引。這種情況下,可以在 SELECT 語句中使用 USE INDEX (indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制 MYSQL 忽略索引

key_len:  使用的索引的長度。在不損失精確性的情況,長度越短越好。

ref:  顯示索引的哪一列被使用了

rows:   認為必須檢查的用來返回請求資料的行數

extra中出現以下 2 項意味著根本不能使用索引,效率會受到重大影響。應儘可能對此進行優化。

 Using filesort: 表示會對結果使用一個外部索引排序,而不是從表裡按索引次序讀到相關內容。可能在記憶體或者磁碟上進行排序。無法利用索引完成的排序操作稱為“檔案排序”

Using temporary:表示對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢group by

從上述對列名進行介紹,你對效能檢測結果有一個大概的瞭解了吧.其中typeall的地方,都是需要進行優化的地方.在對sql語句的效能檢測最少也應該到達range,這樣才可以忍受.

當你的工作需要對大量的表進行拼寫的時候,或者你在前期設計表結構的時候,你也可以用explain來檢測你的資料庫表是否是高效能的.別再是拼寫完sql語句就算是完事了,記得要對你的sql語句進行效能檢測,這既是對你自己負責,也是對客戶負責.

既然檢測出來的結果有all ,那麼就需要優化,具體怎麼優化,請看我下期部落格.