【问题标题】:MySQL subselect performance question?MySQL子选择性能问题?
【发布时间】:2010-09-25 08:39:06
【问题描述】:

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

如果除了过滤器我不能改变任何东西,还有其他方法可以在没有子选择的情况下获得相同的结果吗?

【问题讨论】:

    标签: mysql optimization subquery


    【解决方案1】:

    我认为第二种方法更有效,因为它只需要一次选择,但可以肯定的是,您应该解释每个查询并检查结果。

    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;
    

    【讨论】:

    • 感谢您的解释提示。似乎在 project.is_template 上添加索引很有帮助。
    【解决方案2】:

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

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

    【讨论】:

    • “一些标准”可以大大减少返回的记录总数。 task.project_id 是必需的,因此这两个查询是等效的。我选择“不在”查询原因然后子选择返回的记录数量比我选择“在”时要少得多。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

      【解决方案4】:

      避免子查询,如 MySQL 版本

      【讨论】:

      • 你在那里用大刷子涂焦油。您能否针对此案发表评论?除非它为每个任务行重复运行子查询,否则很难看出缺乏优化会如何导致显着差异,并且性能测试是否应该是这种情况。
      • 在我见过的每一种情况下,即使查询为 IN 操作返回一组不变的行,子查询也会针对主查询的每个结果运行。
      猜你喜欢
      • 2014-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多