【问题标题】:SQL Performance: Filter first or Join firstSQL 性能:先过滤或先加入
【发布时间】:2018-03-25 10:52:48
【问题描述】:

我有三个表,即员工、部门和申诉。雇员表有超过一百万条记录。我需要找到员工的详细信息,他/她的部门以及他/她提出的申诉。

我可以想到以下两个查询来找到结果:

1.先过滤记录,只获取需要数据的员工的记录:

SELECT * FROM (SELECT * FROM Employees WHERE EmployeeID= @EmployeeID) Emp    
LEFT JOIN Department Dpt ON Emp.EmployeeID= Dpt.EmployeeID    
LEFT JOIN Grievance Grv ON Emp.EmployeeID= Grv.EmployeeID;

2。先加入:

SELECT * FROM Employees Emp    
    LEFT JOIN Department Dpt ON Emp.EmployeeID= Dpt.EmployeeID    
    LEFT JOIN Grievance Grv ON Emp.EmployeeID= Grv.EmployeeID    
WHERE EmployeeID= @EmployeeID);

如果我们考虑以 FROM>INNER JOIN>OUTER JOIN>WHERE>....SELECT 开头的 SQL 逻辑处理顺序,第一个查询应该执行得更好/更快,因为内部查询中只有一条记录,并且将与进一步的表连接。 但是,在执行这两个查询时,我没有发现任何性能差异,而且两个查询几乎都需要相同的时间。

请检查一下,让我知道我哪里想错了吗?

【问题讨论】:

  • 你可以使用“实际执行计划”吗? [Ctrl + M] 在运行查询之前?
  • 如果您查看执行计划,您应该能够看到两个查询的数据是如何获取的。
  • 查看估计/实际计划。 SQL 立即向表Employees 抛出一个谓词值
  • SQL 语言是声明性的而不是过程性的,因此您描述的是所需的结果,而不是指导 SQL Server 如何处理查询。优化器可以重构语义相同的查询,以便以最有效的方式返回结果。
  • 处理您的索引和统计数据 - 这些是大型表性能的关键

标签: sql sql-server join left-join inner-query


【解决方案1】:

别担心。查询的处理分三个阶段进行:

  1. 解析
  2. 编译
  3. 执行

编译阶段的一个关键部分是优化。这是 SQL 引擎确定最佳执行计划的时候。

在您的第一个查询中,SQL Server 将忽略子查询。这两个查询应该有相同的执行计划。

注意:并非所有数据库都如此。一些更简单的数据库实际上实现了子查询。

从美学的角度来看,我更喜欢第二个查询——只是为了避免不必要的子查询,因此所有过滤都在外部 where 子句中(这是预期的)。

【讨论】:

    【解决方案2】:

    您的一般前提是 SQL 的错误方法。

    首先编写查询,然后让您的数据库制定计划。仅当您发现问题时才进行优化,否则您通常能够更好地利用您的时间。

    查询计划会告诉你发生了什么。

    【讨论】:

      【解决方案3】:

      您使用的表格的顺序无关紧要。 除非您使用我不推荐的查询提示(FORCE ORDER)。 无论如何,您正在利用星号 (*) 来优化 SQL Server 的执行计划。仅使用您真正需要的列。重建统计信息以确保 SQL Server 有足够的信息来构建最佳执行计划。

      【讨论】:

        【解决方案4】:

        没有“逻辑处理顺序”,除非您的意思是“使用子表达式 1:1 评估查询”,但这无关紧要,因为 DBMS 不这样做。你的错误想法是认为你有一个合理的 DBMS 执行心智模型。阅读有关 SQL 作为声明性的信息。关于查询执行/实施——整本书都在等待。只需简单直接地设计和查询,了解索引和计划以及 DBMS 的基本优化模型/策略即可。

        Which query is more performant?

        【讨论】:

          猜你喜欢
          • 2023-03-25
          • 2012-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-02
          • 2015-11-13
          • 1970-01-01
          • 2015-08-10
          相关资源
          最近更新 更多