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
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。
從上述對列名進行介紹,你對效能檢測結果有一個大概的瞭解了吧.其中type為all的地方,都是需要進行優化的地方.在對sql語句的效能檢測最少也應該到達range,這樣才可以忍受.
當你的工作需要對大量的表進行拼寫的時候,或者你在前期設計表結構的時候,你也可以用explain來檢測你的資料庫表是否是高效能的.別再是拼寫完sql語句就算是完事了,記得要對你的sql語句進行效能檢測,這既是對你自己負責,也是對客戶負責.
既然檢測出來的結果有all ,那麼就需要優化,具體怎麼優化,請看我下期部落格.