天天看點

mysql5.7官網直譯SQL語句優化--where條件查詢優化

這部分讨論的優化是針對WHERE條件的。通過SELECT語句來舉例,但是同樣的優化也适用于DELETE和UPDATE中的WHERE語句。

   注意:因為mysql優化器的工作一直在繼續,是以不可能把mysql執行優化的全部資訊都展示在這裡。

你也許會在犧牲可讀性的前提下重寫查詢進而來提高算法操作速度。因為mysql會自動去做同樣的優化操作,是以你應該避免這樣做,進而保證你的查詢更加可了解且具有更加可維護的格式。mysql完成的一些優化如下:

>移除不必要的括号;

例如:((a AND b) AND c OR (((a AND b) AND (c AND d))))-> (a AND b AND c) OR (a AND b AND c AND d)

>合并常數;

例如: (a<b AND b=c) AND a=5-> b>5 AND b=c AND a=5 #因為a是常數5,是以将b>a優化為b>5

>去除常數條件(如果是合并常數需要的話):

例如:(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)-> B=5 OR B=6 #第一個括号内的條件等價于B=5,而第二個括号内的條件等價于B=6,是以最終優化為後者形式的條件查詢

>在索引中使用的常量表達式隻會被評價一次。

>對一張簡單表執行不帶WHERE條件的count(*)查詢,對于myisam和記憶體表而言,結果直接從表資訊中擷取。當然這個也可以同樣完成,對于任何單表的NOT NUll表達式查詢。

>對于非常量表達式的早期檢查,mysql很快發現一些select語句是不可能有結果傳回的。

>将having條件和where條件合并,如果你沒有使用group by或者其他聚合函數的話(count(),min(),max()等)。

>對于連接配接中的每張表,一個簡單的where條件被建立,隻為更快的where 評估和盡可能的過濾無用資料。

>所有的常量表應該在查詢中任何其他表讀取之前讀取。常量表可能是如下:

  1)一個空表或者是隻有一行的表

  2)在主鍵或者是唯一索引列上使用了where條件的表,即全部索引和常量表達式比較并且被定義為非 NULL

  所有下清單都将被看為是常量表:

  select * from t where primary_key=1

  select * from t1,t2 where t1.primary_key=1 and t2.primary_key=t1.id;

>通過嘗試所有可能的表連接配接進而找到最優的表連接配接。如果在order by 和group by條件中的列都是來自同一張表,那麼該表應該首先被連接配接。

>如果order by和group by 條件是不同的列,或者是order by或者group by中的列來自其他表,而不是第一張連接配接隊列中的表,則會建立一張臨時表。

>如果你使用了SQL_SMALL_RESULT調整器,mysql會使用一個記憶體臨時表。

>除非優化器相信表掃描會更有效,否則一定會查詢每張表的索引,并且使用最好的索引來完成查詢。曾經,是否要使用全表掃描的依據是最好索引是否超越表中的30%,但現在已經沒有一個固定的比例來決定是使用索引還是全表掃描。現在的優化器更加複雜,是以選擇條件也包含了一些額外因子比方說表大小,表中的行數,和I/O塊的大小。

>在一些情況下,MYSQL能夠查詢行資料通過索引,而不用查詢資料檔案。如果索引中的全部列都是數字,那麼隻需要解析索引數就可以完成查詢。

>在每一行輸出之前,那些在having條件沒有比對上的行就會被忽略掉。

一些查詢特别快的例子如下:

select count(*) from tb1_name;

select min(key_part1),max(key_part1) from tb1_name;

select max(key_part2) from tb1_name where key_art1=constant;

select .... from tb1_name order by key_part1,key_part2,... limit 10;

select .... from tb1_name order by key_part1 desc,key_part2 desc,... limit 10;

mysql隻會使用索引樹來解析下列查詢,假設索引列是數字:

SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;

SELECT COUNT(*) FROM tbl_name

  WHERE key_part1=val1 AND key_part2=val2;

SELECT key_part2 FROM tbl_name GROUP BY key_part1;

下列查詢通過索引來查詢行,而不需要單獨再排序一次。

到此關于where條件優化的解析就結束了。接下來要說明的是8.2.1.2的範圍優化(range optimization)。