MySQL 5.7 ref ——13.2.10.10優化子查詢html
10、子查詢的優化mysql
開發正在進行中,所以從長遠來看,沒有什麼優化建議是可靠的。如下列表提供了一些您可能想要使用的有趣技巧。See also Section 8.2.2, 「Optimizing Subqueries, Derived Tables, and View References」.sql
10.1 優化子查詢中行的數量或順序數據庫
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);
10.2 用子查詢替換鏈接服務器
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;
10.3工具
某些子查詢能夠轉換爲鏈接,以便與不支持子查詢的舊版MySQL兼容。可是,在某些狀況下,將子查詢轉換爲鏈接可能會提升性能。性能
10.4 子句從外部移動到子查詢內部測試
例如,用上面的查詢代替下面的:優化
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;
10.5 使用行子查詢而不是相關子查詢。
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);
10.6
使用
NOT (a = ANY (...))
而不是
a <> ALL (...)
10.7
使用
x = ANY (table containing (1,2))
而不是
x=1 OR x=2.
10.8
使用
=ANY
而不是
EXISTS
10.9
對於始終返回一行的不相關子查詢,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工具,您能夠了解在您本身的狀況下有什麼幫助。See Section 12.15, 「Information Functions」.
MySQL本身也會作出一些優化:
... IN (SELECT indexed_column FROM single_table ...)
value {ALL|ANY|SOME} {> | < | >= | <=} (uncorrelated subquery)
例如,對這個WHERE子句
WHERE 5 > ALL (SELECT x FROM t)
優化器可能會像這樣對待:
WHERE 5 > (SELECT MAX(x) FROM t)
See also MySQL Internals: How MySQL Transforms Subqueries.
11、將子查詢重寫爲鏈接
有時,除了使用子查詢以外,還有其餘方法能夠測試一組值中的成員資格。
一樣,在某些狀況下,不只能夠將查詢重寫爲沒有子查詢的語句,還可能比使用子查詢更加高效。IN()構造器就是如此。
例如,這個查詢:
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
能夠被重寫爲:
SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;
查詢:
SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2); SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);
能夠被重寫爲:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
LEFT [OUTER] JOIN能夠比等效子查詢更快,由於服務器可能可以更好地優化它——這個事實並不是僅針對MySQL Server。
在SQL-92以前,外鏈接不存在,所以子查詢是執行某些操做的惟一方法。今天,MySQL Server和許多其餘現代數據庫系統提供了普遍的外鏈接類型。
MySQL Server支持多表DELETE語句,可用於根據一個表甚至多個表中的信息同時有效地刪除行。還支持多表UPDATE語句。See Section 13.2.2, 「DELETE Syntax」, and Section 13.2.11, 「UPDATE Syntax」.