SQL 性能:先筛选或先联接



我有三个表格,即员工、部门和申诉。"员工"表包含超过 100 万条记录。我需要找到员工的详细信息,他/她的部门以及他/她提出的不满。

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

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,第一个查询应该执行得更好/更快,因为内部查询中只有一条记录,并将与其他表联接。但是,在执行这两个查询时,我没有发现任何性能差异,并且两个查询花费的时间几乎相同。

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

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

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

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

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

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

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

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

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

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

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

哪个查询的性能更高?

您使用的表的顺序无关紧要。除非你使用查询提示(强制顺序),我不建议这样做。无论如何,您正在失去通过使用星号(*)来优化SQL Server执行计划的机会。仅使用您真正需要的列。重新生成统计信息以确保 SQL Server 具有足够的信息来生成最佳执行计划。

最新更新