MySQL where優化

MySQL where

該節討論爲處理WHERE子句而進行的優化。例子中使用了SELECT語句,但相同的優化也適用DELETE和UPDATE語句中的WHERE子句。mysql

請注意對MySQL優化器的工做在不斷進行中,所以該節並不完善。MySQL執行了大量的優化,本文中所列的並不詳盡。sql

下面列出了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)

·         常量重疊:spa

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

·         去除常量條件(因爲常量重疊須要):排序

·                   (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
·                -> B=5 OR B=6

·         索引使用的常數表達式僅計算一次。索引

  • 對於MyISAM和HEAP表,在一個單個表上的沒有一個WHERE的COUNT(*)直接從表中檢索信息。當僅使用一個表時,對NOT NULL表達式也這樣作。
  • 無效常數表達式的早期檢測。MySQL快速檢測某些SELECT語句是不可能的而且不返回行。
  • 若是不使用GROUP BY或分組函數(COUNT()、MIN()……),HAVING與WHERE合併。
  • 對於聯接內的每一個表,構造一個更簡單的WHERE以便更快地對錶進行WHERE計算而且也儘快跳過記錄。
  • 全部常數的表在查詢中比其它表先讀出。常數表爲:
    • 空表或只有1行的表。
    • 與在一個PRIMARY KEY或UNIQUE索引的WHERE子句一塊兒使用的表,這裏全部的索引部分使用常數表達式而且索引部分被定義爲NOT NULL。

下列的全部表用做常數表:隊列

mysql> SELECT * FROM t WHERE primary_key=1;
mysql> 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 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;

下列查詢僅使用索引樹就能夠解決(假設索引的列爲數值型):ci

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, 
相關文章
相關標籤/搜索