0

我需要有关 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 <> 1 的项目数量可能很多。

如果我除了过滤之外什么都不能改变,还有其他方法可以在没有子选择的情况下获得相同的结果吗?

4

4 回答 4

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;
于 2008-12-04T16:03:13.790 回答
1

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

select tasks.*
from tasks
where 
  some criteria
  and task.project_id in (select id from project where project.is_template <> 1);
于 2008-12-04T16:14:49.723 回答
0

我认为第一个可能会更好地扩展:

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

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

相比之下,子查询仅从每个表中选择相关行。

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

于 2008-12-04T16:18:59.873 回答
0

避免像 MySQL 版本 < 6.0 中的瘟疫之类的子查询,考虑到它仍处于开发的 alpha 阶段,我怀疑你正在使用 6.0。AFAIK,MySQL 优化器根本不能很好地处理子查询。一些主要的工作已经用于改进 6.0 的优化器,并且子查询现在工作得更好,但这些变化并没有渗透到 5.0 或 5.1 系列中。

于 2008-12-04T16:19:15.643 回答