开发过程不断进展,所以从长远来看,没有一个可靠的优化技巧。有些技巧您可能会感兴趣,并原意采用:
· 有些子句会影响在子查询中的行的数量和顺序。使用这类子句。例如:
· 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/获取。