1. 程式人生 > >Mysql查詢優化——Explain使用

Mysql查詢優化——Explain使用

The palest ink is better than best memory——好記性不如爛筆頭。2012補記

一、關鍵詞

SQL優化、執行計劃、explain、using filesort、using temporary

二、摘要

開發中,為滿足一業務功能,使用mysql書寫sql時,一條sql往往有多種寫法,那麼我們就需要選擇執行效率比較高的sql。
因此要比較分析sql的執行過程,且同一條sql我們要比較選擇使用最優索引。
通過explain命令可以得到:
這裡寫圖片描述

整體執行順序(子查詢)、查詢型別、使用什麼表(表 泛指)、資料訪問/讀取操作型別、使用到索引等。

先整體瞭解下SQL查詢的基本執行過程:

1)應用通過MySQL API把查詢命令傳送給MySQL伺服器,然後被解析

2)檢查許可權、MySQL optimizer進行優化,經過解析和優化後的查詢命令被編譯為CPU可執行的二進位制形式的查詢計劃(query
plan),並可以被快取

3)如果存在索引,那麼先掃描索引,如果資料被索引覆蓋,那麼不需要額外的查詢,如果不是,根據索引查詢和讀取對應的記錄

4)如果有關聯查詢,查詢次序是掃描第一張表找到滿足條件的記錄,按照第一張表和第二張表的關聯鍵值,掃描第二張表查詢滿足條件的記錄,按此順序迴圈

5)輸出查詢結果,並記錄binary logs

三、Explain返回資訊:

列名 說明
id 執行編號,標識select所屬的行。如果在語句中沒子查詢或關聯查詢,只有唯一的select,每行都將顯示1。否則,內層的select語句一般會順序編號,對應於其在原始語句中的位置
select_type 顯示本行是簡單或複雜select。如果查詢有任何複雜的子查詢,則最外層標記為PRIMARY(DERIVED、UNION、UNION RESUlT)
table 訪問引用哪個表(引用某個查詢,如“derived3”)
type 資料訪問/讀取操作型別(ALL、index、range、ref、eq_ref、const/system、NULL)
possible_keys 揭示哪一些索引可能有利於高效的查詢
key 顯示mysql決定採用哪個索引來優化查詢
key_len 顯示mysql在索引裡使用的位元組數
ref 顯示了之前的表在key列記錄的索引中查詢值所用的列或常量
rows 為了找到所需的行而需要讀取的行數,估算值,不精確。通過把所有rows列值相乘,可粗略估算整個查詢會檢查的行數
Extra 額外資訊,如using index、filesort等
  • select_type列:
select_type型別 說明
SUBQUERY 在select列表中的子查詢,如SELECT *,(SELECT id FROM product_info) AS id FROM product_info
DERIVED 在from子語句中子查詢,如SELECT * FROM product_info p1 ,(SELECT * FROM product_info) p2.Mysql會遞迴執行,並把結果放到臨時表中
UNION 在UNION中第二個和隨後的SELECT被標記為UNION
UNION RESULT 用來從UNION的匿名臨時表檢索結果的SELECT被標記為UNION RESULT
  • type列(依次從最差到最優):
type型別 說明
All 最壞的情況,從頭到尾全表掃描
index 和全表掃描一樣。只是掃描表的時候按照索引次序進行而不是行。主要優點就是避免了排序, 但是開銷仍然非常大。如在Extra列看到Using index,說明正在使用覆蓋索引,只掃描索引的資料,它比按索引次序全表掃描的開銷要小很多
range 範圍掃描,一個有限制的索引掃描。key 列顯示使用了哪個索引。當使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比較關鍵字列時,可以使用 range
ref 一種索引訪問,它返回所有匹配某個單個值的行。此類索引訪問只有當使用非唯一性索引或唯一性索引非唯一性字首時才會發生
eq_ref 最多隻返回一條符合條件的記錄。使用唯一性索引或主鍵查詢時會發生 (高效)
const/system 當主鍵放入where子句時,mysql把這個查詢轉為一個常量(高效)
Null 意味說mysql能在優化階段分解查詢語句,在執行階段甚至用不到訪問表或索引(高效)
  • Extra列常見情況(需要優化):
Extra情況 說明
Using temporary 表示 MySQL 在對查詢結果排序時使用臨時表。常見於排序 order by 和分組查詢 group by
Using filesort 表示 MySQL 會對結果使用一個外部索引排序,而不是從表裡按索引次序讀到相關內容。可能在記憶體或者磁碟上進行排序。MySQL 中無法利用索引完成的排序操作稱為“檔案排序”

四、事例(2012公司專案):

案例1:

EXPLAIN
SELECT e1.*,0 AS 'hasCount' FROM eticketdetail e1 WHERE e1.brandUserId =5303 AND e1.status =1 AND e1.parentId =0 
UNION  
SELECT e2.*,0 AS 'hasCount' FROM eticketdetail e2 WHERE e2.status =1 AND  e2.id IN (SELECT e3.parentId FROM eticketdetail e3 WHERE  e3.parentId >0 AND e3.brandUserId = 5303)
ORDER BY createtime LIMIT 0,10

這裡寫圖片描述

EXPLAIN
SELECT e1.*,0 AS 'hasCount' FROM eticketdetail e1 WHERE e1.brandUserId =5303 AND e1.status =1 AND e1.parentId =0 
UNION  
SELECT e2.*,0 AS 'hasCount' FROM eticketdetail e2 WHERE e2.status =1 AND  EXISTS (SELECT 1 FROM eticketdetail e3 WHERE  e3.parentId >0 AND e3.brandUserId = 5303)
ORDER BY createtime LIMIT 0,10

這裡寫圖片描述

EXPLAIN
SELECT e1.*,0 AS 'hasCount' FROM eticketdetail e1 WHERE e1.brandUserId =5303 AND e1.status =1 AND e1.parentId =0 
UNION  
SELECT e2.*,0 AS 'hasCount' FROM eticketdetail e2 INNER JOIN (SELECT e3.parentId FROM eticketdetail e3 WHERE  e3.parentId >0 AND e3.brandUserId = 5303) tab ON e2.id = tab.parentid  WHERE e2.status =1 
ORDER BY createtime LIMIT 0,10

這裡寫圖片描述

案例2:

第一種寫法:
SELECT 
  mp.*
FROM memberpromotion mp
  INNER JOIN memberpromotionlocation mpl
    ON mpl.MemberPromotionID = mp.ID
WHERE mp.status = 1
    AND mp.BrandUserID = 2402
AND mpl.shopId = 0
第二種寫法:
SELECT 
  mp.*
FROM (SELECT * FROM memberpromotion memb WHERE memb.BrandUserID = 2402) mp
  INNER JOIN memberpromotionlocation mpl
    ON mpl.MemberPromotionID = mp.ID
WHERE mp.status = 1
AND mpl.shopId = 0

這裡寫圖片描述

案例3:

第一幅圖語句:
SELECT SQL_NO_CACHE
  e.*,
  (SELECT
     COUNT(id)
   FROM eticketdetail
   WHERE userId = e.userId
       AND orderId = e.orderId
       AND promotionId = e.promotionId
       AND promotionProductId = e.promotionProductId
       AND STATUS != 3
       AND STATUS = 0 ) AS 'hasCount'
FROM eticketdetail e
WHERE userId = 5302
    AND isGift = 0 AND isReal = 0 AND STATUS = 0
GROUP BY userId,orderId,promotionId,promotionProductId 
UNION 
SELECT e.*, 1    AS 'hasCount' FROM eticketdetail e
WHERE userId = 5302  AND isGift = 1 AND STATUS = 0
ORDER BY CreateTime DESC
第二幅圖語句:(UNION改為UNION ALL)
SELECT SQL_NO_CACHE
  e.*,
  (SELECT
     COUNT(id)
   FROM eticketdetail
   WHERE userId = e.userId
       AND orderId = e.orderId
       AND promotionId = e.promotionId
       AND promotionProductId = e.promotionProductId
       AND STATUS != 3
       AND STATUS = 0 ) AS 'hasCount'
FROM eticketdetail e
WHERE userId = 5302
    AND isGift = 0
    AND isReal = 0
    AND STATUS = 0
GROUP BY userId,orderId,promotionId,promotionProductId 
UNION ALL
SELECT e.*, 1    AS 'hasCount' FROM eticketdetail e
WHERE userId = 5302  AND isGift = 1 AND STATUS = 0
ORDER BY CreateTime DESC
第三幅圖: 增加userId索引後
第四幅圖:
SELECT 
  e.*,
  tab.t AS 'hasCount'
FROM eticketdetail e 
INNER JOIN (
    SELECT id,COUNT(id) AS t FROM eticketdetail WHERE userid=5302  AND isGift = 0 AND isReal = 0 AND STATUS != 3 AND STATUS = 0 GROUP BY orderId,promotionId,promotionProductId ORDER BY NULL
) tab ON tab.id = e.ID
WHERE userId = 5302
    AND isGift = 0
    AND isReal = 0
    AND STATUS = 0
GROUP BY orderId,promotionId,promotionProductId 
UNION ALL
SELECT e.*, 1    AS 'hasCount' FROM eticketdetail e
WHERE userId =5302  AND isGift = 1 AND STATUS = 0
ORDER BY CreateTime DESC

這裡寫圖片描述

這玩意,只有動手多折騰比較幾下~

五、參考:

相關推薦

Mysql查詢優化——Explain使用

The palest ink is better than best memory——好記性不如爛筆頭。2012補記 一、關鍵詞 SQL優化、執行計劃、explain、using filesort、using temporary 二、

MySQL查詢優化explain的深入解析

extra lin sub const query gin alt com nec 本篇文章是對MySQL查詢優化中的explain進行了詳細的分析介紹,需要的朋友參考下 在分析查詢性能時,考慮EXPLAIN關鍵字同樣很管用。EXPLAIN關鍵字一般放在SELECT查

關聯查詢和多次查詢的點 以及 MySQL查詢優化 EXPLAIN詳解

        對於欄位比較多的表,如果有些欄位的使用頻率很低,可以將這些欄位分離出來形成新表。因為當一個表的資料量很大時,會由於使用頻率低的欄位的存在而變慢。2. 增加中間表        對於需要經常聯合查詢的表,可以建立中間表以提高查詢效率。通過建立中間表,把需要經常聯合查詢的資料插入到中間表中,然後將

MySQL查詢優化語句--explain

一、MySQL 查詢優化器是如何工作的 MySQL 查詢優化器有幾個目標,但是其中最主要的目標是儘可能地使用索引,並且使用最嚴&#26684;的索引來消除儘可能多的資料行。最終目標是提交 SELECT 語句查詢資料行,而不是排除資料行。優化器試圖排除資料行的原因在於

MySQL查詢優化利刃-EXPLAIN

#### 有一個 **?** 遇到這樣一個疑問:當where查詢中In一個索引欄位作為條件,那麼在查詢中還會使用到索引嗎? ```sql SELECT * FROM table_name WHERE column_index in (expr) ``` 上面的sql語句檢索會使用到索引嗎?帶著這個問題,

MySQL查詢優化

mysql 1、簡介 一個好的web應用,最重要的一點是有著優秀的訪問性能。數據庫MySQL是web應用的組成部分,也是決定其性能的重要部分。所以提升MySQL的性能至關重要。 MySQL性能的提升可分為三部分,包括硬件、網絡、軟件。其中硬件、網絡取決於公司的財力,需要白嘩嘩的銀兩,這裏

Mysql查詢優化從入門到跑路(三)查詢的基本操作

限制 sql 數據 單位 二維 一行 用戶 div 答案 查詢的基本操作 1.選擇操作 對應的是限制條件,操作對象是二維表的行。 優化方式:選擇操作下推 目的:盡量減少連接操作前的元租數,使得中間臨時關系盡量少(元祖數少,連接得到的元組數就少) 好處

mysql 千萬級數據查詢效率實踐,分析 mysql查詢優化實踐--本文只做了一部分,僅供參考

open ges -a 效率 2萬 https ini class cnblogs 數據量, 1300萬的表加上112萬的表 註意: 本文只做了部分優化,並不全面,僅供參考, 歡迎指點. 請移步tim查看,因為寫的時候在tim寫的,粘貼過來截圖有問題,就直接上鏈接了.

關於MySQL查詢優化 の 30條忠告

合計 num pda 記錄 同時 運行時 mys int 字型 擼自:http://www.jincon.com/archives/120/ 1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應盡量避免在 wh

MySQL 查詢優化

優化查詢優化常用策略 1、優化數據訪問:應用程序應該減少對數據庫的數據訪問,數據庫應該減少實際掃描的記錄數 例如,Redis緩存,避免"select * from table" 2、重寫SQL 對於需要進行大量數據的操作,可以分批執行,以減少對生產系統的影響,從而緩解復

MySQL查詢優化方法總結

系統表 所有 全文檢索 更新 系統 and 插入 upd 一個 1.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。 2.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及頻繁的

mysql 查詢優化 ~ 善用profie利器

發送 ems ops nor 排序 ring free query exec 一 簡介:利用profile分析慢語句的過程有助於我們進行語句的優化 二 執行過程 set profiling=1; set profiling=0; 2 執行sql 3 查看過程消耗

mysql 查詢優化 高效能mysql筆記

衡量查詢效能的三個指標 返回的行數。 掃描的行數:查詢所需要掃描的行數。 相應的時間:服務時間(執行sql的時間)+排隊時間(查詢在等待i/o或者在等待鎖) 優化慢查詢 採用索引覆蓋以及延時索引  1重構查詢的方式     可以複雜查詢分為多個簡單查詢 &

mysql 查詢優化 ~ 索引失效

一 explain  1 掃描行數根據的是表的統計元資料  2 索引的元資料具體指的就是show index from查到的索引的區分度,索引的區分度越高越好   3 表的元資料是定期收集,所以可能不準確  4 如果感覺explain不準確,可以用analyze tab

mysql 查詢優化 ~ select count 知多少

一 簡介:今天咱們來聊聊mysql的查詢總數 二 具體介紹      1 從引擎層面說       myisam  myisam的掃描總行數是非常快的,這是因為myisam會將表的總行數儲存起來,定期維護,但是注意,一旦加入where

010 --MySQL查詢優化器的侷限性

MySQL的萬能"巢狀迴圈"並不是對每種查詢都是最優的。不過還好,mysql查詢優化器只對少部分查詢不適用,而且我們往往可以通過改寫查詢讓mysql高效的完成工作。在這我們先來看看mysql優化器有哪些侷限性: 1.關聯子查詢 mysql的子查詢實現得非常糟糕。最糟糕得一類查詢是where條件中包含in(

010 --MySQL查詢優化器的局限性

通過 全表掃描 exit you clas fir 找到 use *** MySQL的萬能"嵌套循環"並不是對每種查詢都是最優的。不過還好,mysql查詢優化器只對少部分查詢不適用,而且我們往往可以通過改寫查詢讓mysql高效的完成工作。在這我們先來看看mysql優化器有哪

淺談MySql查詢優化

1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。  2.應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。  3.應儘量避免在 where 子句中對欄位進行 nu

MySQL查詢優化之IS NULL的優化

原文地址:https://dev.mysql.com/doc/refman/5.7/en/is-null-optimization.html 譯文: 8.2.1.13 IS NULL 優化 MySQL可以對col_name IS NULL執行與col_name = consta

MySQL查詢優化之條件過濾

原文地址:https://dev.mysql.com/doc/refman/5.7/en/condition-filtering.html 譯文: 8.2.1.12 條件過濾 在連線處理中,字首行是連線中從一個表傳遞到另一個表的行。通常,優化器試圖將字首計數較低的表放在連線的早期,以防止