如何优化这个SQL语句?

时间:2015-02-14 12:42:31

标签: mysql sql

我需要根据一个表(tableA)的选择结果从表列表(list1,list2,list3,...)中进行选择。如何重用该表中的选择结果(tableA)?

我的解决方案是

select * from list1 where list1.id in(select id from tableA where ...)
select * from list2 where list2.id in(select id from tableA where ...)
select * from list3 where list3.id in(select id from tableA where ...)
...

在我的解决方案中,从tableA中选择id,其中...... 执行3次,可能需要很长时间,效率不高。 在我的想象中,从tableA中选择id,其中...... 应该只执行一次。

任何人都可以帮助我吗?

4 个答案:

答案 0 :(得分:2)

有两点需要注意。首先,在某些版本的MySQL中,exists版本效率更高:

select *
from list1
where exists (select 1 from tableA a where a.id = list1.id and (...))
. . .

其次,您希望在tableA上拥有正确的索引来优化查询。基本上,正确的索引是一个复合索引,第一个键是idwhere子句中的列跟随。

在索引中排序列的最佳方法取决于where条件。如果条件是由and连接的所有相等条件,则排序无关紧要。

答案 1 :(得分:1)

您可以使用临时表将子查询的结果存储在内存中,并使用简单的IN (select id from tmptable)替换子查询。我假设您的原始子查询稍微复杂一些,可能包含复杂的WHERE条件:

CREATE TEMPORARY TABLE tmptable 
AS SELECT id FROM tableA WHERE complex = condition AND more = conditions;

SELECT * FROM list1 l WHERE l.id IN (SELECT id FROM tmptable)
SELECT * FROM list2 l WHERE l.id IN (SELECT id FROM tmptable)
...

因此,复杂查询只执行一次,结果存储在内存中,并被以下查询重用。

答案 2 :(得分:0)

如果所有3个SELECT都返回兼容的结果,您可以尝试使用UNION ALL组合它们:

select *
FROM
 (
   select * from list1
   UNION ALL
   select * from list2
   UNION ALL
   select * from list3
 ) as dt
 where id in (select id from tableA where ...)

但我怀疑MySQL的优化器可以很好地解决这个问题......

答案 3 :(得分:-1)

没有更有效的方法来做到这一点。没有解决这个基本事实,你必须将两个列表相互比较n次,其中n是你拥有的列表表的数量。

这有点类似于以下一组补充:

a + 5 = ?
b + 5 = ?
c + 5 = ?
d + 5 = ?

嘿,有没有办法优化这个?毕竟我每次只加5!

不,不是真的。在这个例子中,您可以编写一个函数,该函数将5添加到某个东西,这将减少代码量,并且从DRY角度来看更好。但是,这不会在减少执行时间方面“优化”它。