开发仍在进行中,因此从长远来看,没有任何优化技巧是可靠的。下面的列表提供了一些您可能想要尝试的有趣技巧。另见 第 8.2.2 节,“优化子查询和派生表”。
使用影响子查询中行的数量或顺序的子查询子句。例如:
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.10.11 节,“将子查询重写为连接”。
将子句从外部移动到子查询内部。例如,使用此查询:
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);使用
NOT (a = ANY (...))而不是a <> ALL (...)。使用而不是。
x = ANY (table containing (1,2))x=1 OR x=2使用
= ANY而不是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 工具,您可以了解在您自己的情况下有什么帮助。请参阅
第 12.16 节,“信息功能”。
MySQL本身做的一些优化是:
MySQL 只执行一次不相关的子查询。用于
EXPLAIN确保给定的子查询确实是不相关的。MySQL 重写
IN、ALL、ANY和SOME子查询以试图利用子查询中的选择列表列被索引的可能性。MySQL 将以下形式的子查询替换为索引查找函数,该函数
EXPLAIN描述为特殊的连接类型(unique_subquery或index_subquery):... IN (SELECT indexed_column FROM single_table ...)MIN()MySQL 使用涉及or 的表达式增强以下形式的表达式MAX(),除非 涉及NULL值或空集:value {ALL|ANY|SOME} {> | < | >= | <=} (uncorrelated subquery)例如,这个
WHERE条款:WHERE 5 > ALL (SELECT x FROM t)优化器可能会这样处理:
WHERE 5 > (SELECT MAX(x) FROM t)
另请参阅 MySQL 内部结构:MySQL 如何转换子查询。