top
Loading...
13.2.8.10.優化子查詢
13.2.8.10. 優化子查詢

開發過程不斷進展,所以從長遠來看,沒有一個可靠的優化技巧。有些技巧您可能會感興趣,并原意采用:

·         有些子句會影響在子查詢中的行的數量和順序。使用這類子句。例如:

·                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, ANYSOME子查詢,目的是如果子查詢中的select-list列已編制索引,則能發揮出此優勢。

·         MySQL使用index-lookup函數代替以下格式的子查詢。EXPLAIN把此函數描述為特殊的聯合類型(unique_subqueryindex_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/獲取。

作者:mysql.com
來源:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html
北斗有巢氏 有巢氏北斗