開發過程不斷進展,所以從長遠來看,沒有一個可靠的優化技巧。有些技巧您可能會感興趣,并原意采用:
· 有些子句會影響在子查詢中的行的數量和順序。使用這類子句。例如:
· SELECT * FROM t1 WHERE t1.column1 IN
· (SELECT column1 FROM t2 ORDER BY column1);
· SELECT * FROM t1 WHERE t1.column1 IN
· (SELECT DISTINCT column1 FROM t2);
· SELECT * FROM t1 WHERE EXISTS
· (SELECT * FROM t2 LIMIT 1);
· 用子查詢替換聯合。例如,試進行如下操作:
· SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
· SELECT column1 FROM t2);
代替如下操作:
SELECT DISTINCT t1.column1 FROM t1, t2
WHERE t1.column1 = t2.column1;
· 部分子查詢可以被轉換為聯合,以便與不支持子查詢的舊版本的MySQL相兼容。不過,在有些情況下,把子查詢轉化為聯合可以提高效果。請參見13.2.8.11節,“把子查詢作為用于早期MySQL版本的聯合進行改寫”。
· 把子句從子查詢的外部轉移到內部。例如,使用此查詢:
· SELECT * FROM t1
· WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
代替此查詢:
SELECT * FROM t1
WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
另一個例子是,使用此查詢:
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
代替此查詢:
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
· 使用行子查詢,代替關聯子查詢。舉例說明,使用此查詢:
· SELECT * FROM t1
· WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
代替此查詢:
SELECT * FROM t1
WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
AND t2.column2=t1.column2);
· Use NOT (a = ANY (...)) rather than a <> ALL (...).
· Use x = ANY (table containing (1,2)) rather than x=1 OR x=2.
· Use = ANY rather than EXISTS.
· 對于只返回一行的無關聯子查詢,IN的速度慢于=。舉例說明,使用此查詢:
· SELECT * FROM t1 WHERE t1.col_name
· = (SELECT a FROM t2 WHERE b = some_const);
代替此查詢:
SELECT * FROM t1 WHERE t1.col_name
IN (SELECT a FROM t2 WHERE b = some_const);
使用這些技巧可以使程序更快或更慢。使用BENCHMARK()函數等MySQL工具,您可以了解到在您所處的情況下,哪些技巧會有幫助。
MySQL本身進行的部分優化包括:
· MySQL只執行一次無關聯子查詢。使用EXPLAIN確認給定的子查詢確實是無關聯的。
· MySQL改寫IN, ALL, ANY和SOME子查詢,目的是如果子查詢中的select-list列已編制索引,則能發揮出此優勢。
· MySQL使用index-lookup函數代替以下格式的子查詢。EXPLAIN把此函數描述為特殊的聯合類型(unique_subquery或index_subquery):
· ... IN (SELECT indexed_column FROM single_table ...)
· 當表達式中不包含NULL值或空集時,MySQL使用一個包含MIN()或MAX()的表達式,對以下格式的表達式進行擴展:
· value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)
例如,本WHERE子句:
WHERE 5 > ALL (SELECT x FROM t)
可以用優化符進行如下處理:
WHERE 5 > (SELECT MAX(x) FROM t)
在MySQL內部手冊中有一章名為“MySQL如何轉換子查詢”,可以從http://dev.mysql.com/doc/獲取。