mysql 8.0 官方文檔翻譯 (一) 之 8.2.1 where 子句優化

8.2.1 where 子句優化

這一塊討論where子句的優化。這些優化適用於select,delete, update語句。

注意:

   因爲mysql的優化工作正在進行中,所以並不是所有的優化都記錄在此。
   
你或許曾經試圖以犧牲可讀性,來優化你的查詢語句,以期獲得更快的運行速率。 現在你大可不必了, 因爲mysql內部, 已經做了許多相似的優化, 使你可以在保持你
的語句更加容易理解,更加具有可維護性的同時,還可以具有不錯的效率。以下爲mysql執行的一些優化:

1.去除掉多餘的花括號

   ((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)

2.常量替換

 (a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5

3.常量條件移除

 (b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=7 AND 5=6)
-> b=5 OR b=6


上述優化,在mysql8.0.14或者更高的版本里,發生在準備階段而不是優化階段,這些優化可以幫助您簡化join查詢。

4.使用索引的常量表達式只會被評估一次

5.從mysql8.0.16開始,如果一個數值類型的列和一個常量進行比較, mysql會檢查這個表達式, 進而決定是進行常量摺疊, 還是移除非法或者超出數值類型列範圍的表達式
例如:

# CREATE TABLE t (c TINYINT UNSIGNED NOT NULL 這意味着 c << 256是恆成立的);
  SELECT * FROM t WHERE c ≪ 256;
-≫ SELECT * FROM t WHERE 1; 

6.如果用count(*)統計基於MyISAM,MEMORY存儲引擎上的單表的數據,且不帶where條件,統計結果可以直接從table information上直接獲得。同樣此優化, 也適用於
任何not null表達式。

7.更早的檢查非法的常量表達式。mysql能夠快速的檢查出一些select語句是不可行的,並快速返回空的結果集。

8.如果having沒有和group by或者其他的聚合函數一起使用, 那麼having子句將會合併成where.

9.在join查詢中, join的每張表如果擁有簡單的where子句, 就可以執行地更快速, 而且使得查詢儘早地跳過不符合條件的記錄。

10.常量表會被優先讀取,長量表必須符合以下條件:
     
     a.空表 或者 只有一行記錄的表
     b.使用主鍵或者唯一鍵而且索引和常量值相比較,而且擁有索引的列被定義爲not null 比如以下查詢會使用到常量表
     
     SELECT * FROM t WHERE primary_key=1;
     SELECT * FROM t1,t2
         WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
         
11.通過嘗試所有可能的方法,可以找到聯接表的最佳聯接組合。如果ORDER BY和GROUP BY子句中的所有列都來自同一個表,
   則在聯接時會優先選擇該表作爲驅動表。
   
12.如果order by和group by所使用的列不同,或者order by或者group by使用的列不是來自同一張表,將會創建臨時表

13.如果使用sql_small_result修飾符,mysql將使用內存中的臨時表

14.除非優化器覺得全表掃描更有效,否則會使用最優的索引來進行查詢。過去,優化器決定使用索引還是全表掃描,依據索引是否跨越全表記錄的30%,如果跨越了
則使用全表掃描。但是現在優化器更加複雜,它的估計基於其他因素,如表大小、行數和I/O塊大小。

15.索引覆蓋

16.在輸出每一行之前,將跳過那些與HAVING子句不匹配的行

一些查詢很快的例子:

SELECT COUNT(*) FROM tbl_name;

SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;

SELECT MAX(key_part2) FROM tbl_name 
  WHERE key_part1=constant; 

SELECT ... FROM tbl_name
  ORDER BY key_part1,key_part2,... LIMIT 10;

SELECT ... FROM tbl_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;

以下查詢使用索引來按排序順序檢索行,而不使用單獨的排序過程:

SELECT ... FROM tbl_name
  ORDER BY key_part1,key_part2,... ;

SELECT ... FROM tbl_name
  ORDER BY key_part1 DESC, key_part2 DESC, ... ;
     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章