SQL 性能:先筛选或先加入

SQL Performance: Filter first or Join first

我有三个 table,即员工、部门和申诉。 Employees table 拥有超过一百万条记录。我需要找到员工、his/her 部门和 him/her 提出的申诉的详细信息。

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

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 逻辑处理顺序,第一个查询应该执行 better/fast因为内部查询中只有一条记录,并将与其他 tables 连接。 但是,在执行这两个查询时,我没有发现任何性能差异,并且两个查询花费的时间几乎相同。

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

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

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

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

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

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

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

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

先编写查询,然后让您的数据库制定计划。只有在发现问题时才进行优化,否则通常可以找到更好地利用时间的方法。

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

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

没有 "logical processing order",除非你的意思是 "evaluating the query 1:1 with subexpressions",但这无关紧要,因为 DBMS 不这样做。你的错误想法是认为你有一个合理的 DBMS 执行心智模型。阅读有关 SQL 的声明。关于查询 execution/implementation--entire 本书等待。直接设计和查询并了解索引和计划以及 DBMS 的基本优化 model/strategy。

Which query is more performant?