2008-12-04 81 views
0

我需要关于MySQL中的子选择性能的建议。由于我无法更改的原因,我无法使用JOIN创建quesry过滤器,我只能在WHERE中添加另一个AND子句。MySQL子查询性能问题?

什么的peformance:

select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id not in (select id from project where project.is_template = 1); 

相比:

select tasks.* 
from tasks, project 
where 
    some criteria 
    and task.project_id = project.id and project.is_template <> 1; 

注意,这里的项目数量相对较少whete is_template = 1,并有可能是大量的项目中is_template <> 1.

如果我不能改变任何东西,但没有过滤器,还有其他方法可以实现同样的结果吗?

回答

5

我相信第二个效率更高,因为它只需要一个选择,但可以肯定的是,您应该解释每个查询并检查结果。

EXPLAIN select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id not in (select id from project where project.is_template = 1); 

EXPLAIN select tasks.* 
from tasks, project 
where 
    some criteria 
    and task.project_id = project.id and project.is_template <> 1; 
+0

感谢您的EXPLAIN提示。 似乎在project.is_template上添加索引有很大帮助。 – Marko 2008-12-04 16:28:13

1

这两者之间有多大的差异可能很大程度上取决于“某些标准”是什么以及使用它提供的索引有哪些机会。但是请注意,如果有任务没有项目,则它们在结果方面并不相同。二是相同的:

select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id in (select id from project where project.is_template <> 1); 
+0

“某些标准”几乎可以减少返回记录的总数。 task.project_id是必需的,所以这两个查询是等价的。 我选择“不在”查询原因然后子选择返回小得多的记录数然后它会如果我选择“在”。 – Marko 2008-12-04 16:27:01

0

我认为首先可以更好的扩展:

当你做一个连接,内部的mysql使一种由两个表的临时表的根据加盟加盟指定的条件。您没有提供连接条件,因此它将创建一个临时表,其中包含针对所有项目列出的所有任务。我很确定(但是请检查解释工具),它在应用任何where子句之前执行此操作。

结果:如果每个都有10个,它将有10 * 10行= 100。随着数字的增加,您可以看到这个数字变大。然后它将这个临时表的位置应用到该临时表。

相反,子查询只选择每个表中的相关行。

但除非缩放是一个问题,我认为它并不重要。

+0

没有人赞同我....我想要一些讨论。 – benlumley 2008-12-04 16:20:21

+0

尝试一个简单的解释来证明自己错了。 – ysth 2008-12-04 20:14:07

0

避免像MySQL版本< 6.0中的鼠疫这样的子查询,我怀疑你使用的是6.0,因为它仍处于开发的alpha阶段。 AFAIK,MySQL优化器根本不处理子查询。一些主要的工作已经在6.0版本中改进了优化器,现在子查询现在运行得好多了,但是这些改变还没有流入5.0或5.1系列。