top
Loading...
7.2.4.MySQL怎樣優化WHERE子句
7.2.4. MySQL怎樣優化WHERE子句

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

請注意對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

·         去除常量條件(由于常量重疊需要)

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

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

  • 對于MyISAMHEAP表,在一個單個表上的沒有一個WHERECOUNT(*)直接從表中檢索信息。當僅使用一個表時,對NOT NULL表達式也這樣做。
  • 無效常數表達式的早期檢測。MySQL快速檢測某些SELECT語句是不可能的并且不返回行。
  • 如果不使用GROUP BY或分組函數(COUNT()MIN()……)HAVINGWHERE合并。
  • 對于聯接內的每個表,構造一個更簡單的WHERE以便更快地對表進行WHERE計算并且也盡快跳過記錄。
  • 所有常數的表在查詢中比其它表先讀出。常數表為:
    • 空表或只有1行的表。
    • 與在一個PRIMARY KEYUNIQUE索引的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 BYGROUP BY的列來自同一個表,那么當聯接時,該表首先被選中。
  • 如果有一個ORDER BY子句和不同的GROUP BY子句,或如果ORDER BYGROUP BY包含聯接隊列中的第一個表之外的其它表的列,則創建一個臨時表。
  • 如果使用SQL_SMALL_RESULTMySQL使用內存中的一個臨時表。
  • 每個表的索引被查詢,并且使用最好的索引,除非優化器認為使用表掃描更有效。是否使用掃描取決于是否最好的索引跨越超過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;

下列查詢僅使用索引樹就可以解決(假設索引的列為數值型)

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, ... ;
作者:mysql.com
來源:http://dev.mysql.com/doc/refman/5.1/zh/optimization.html
北斗有巢氏 有巢氏北斗