我需要有关MySQL中子选择性能的建议。由于我无法更改的原因,我无法使用JOIN创建问题过滤器,我只能在WHERE中添加另一个AND子句。
以下是什么:
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;
请注意,is_template = 1的项目数量相对较少,并且可能存在大量项目,其中is_template&lt;&gt; 1。
如果我不能改变除过滤器之外的任何东西,还有其他方法可以在没有子选择的情况下获得相同的结果吗?
答案 0 :(得分: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;
答案 1 :(得分:1)
两者之间存在多大差异可能在很大程度上取决于“某些标准”是什么以及它提供的使用索引的机会。但请注意,如果有没有项目的任务,它们在结果方面不相同。第二个相当于:
select tasks.*
from tasks
where
some criteria
and task.project_id in (select id from project where project.is_template <> 1);
答案 2 :(得分:0)
我认为第一种可能会更好地扩展:
当你进行连接时,内部mysql会生成一种临时表,该表由根据指定的连接条件连接的两个表组成。您没有给出连接条件,因此它将创建一个临时表,其中列出了针对所有项目的所有任务。我很确定(但请确认解释工具)它在应用任何where子句之前执行此操作。
结果:如果每个都有10个,那么它将有10 * 10行= 100.你可以看到随着数字的增加它变大了。然后它应用此临时表的位置。
相反,子查询仅选择每个表中的相关行。
但除非缩放是一个问题,否则我认为这不重要。
答案 3 :(得分:0)
避免像MySQL版本中的瘟疫那样的子查询&lt; 6.0,我怀疑你是否正在使用6.0,因为它仍处于开发的alpha阶段。 AFAIK,MySQL优化器根本不能很好地处理子查询。一些主要的工作已经用于改进6.0的优化器,现在子查询工作得更好,但这些改变并没有渗透到5.0或5.1系列中。