在很长一段时间内沸腾的问题,在以下两个存储过程中,哪一个会表现得更好。
Proc 1
CREATE PROCEDURE GetEmployeeDetails @EmployeeId uniqueidentifier,
@IncludeDepartmentInfo bit
AS
BEGIN
SELECT * FROM Employees
WHERE Employees.EmployeeId = @EmployeeId
IF (@IncludeDepartmentInfo = 1)
BEGIN
SELECT Departments.* FROM Departments, Employees
WHERE Departments.DepartmentId = Employees.DepartmentId
AND Employees.EmployeeId = @EmployeeId
END
END
Proc 2
CREATE PROCEDURE GetEmployeeDetails @EmployeeId uniqueidentifier,
@IncludeDepartmentInfo bit
AS
BEGIN
SELECT * FROM Employees
WHERE Employees.EmployeeId = @EmployeeId
SELECT Departments.* FROM Departments, Employees
WHERE Departments.DepartmentId = Employees.DepartmentId
AND Employees.EmployeeId = @EmployeeId
AND @IncludeDepartmentInfo = 1
END
两者之间的唯一区别是使用'if statment'。
如果使用@IncludeDepartmentInfo的交替值调用proc 1 / proc 2然后从我的理解proc 2将表现更好,因为它将保留相同的查询计划而不管@IncludeDepartmentInfo的值,而proc1将更改查询计划每次通话
答案真的很明显
PS:这只是一个场景,请不要去显式查询结果而是实例的本质。我非常关注查询优化器结果(在'if和where'及其差异的两种情况下),我知道有很多方面可能影响我在这个问题中要避免的性能。答案 0 :(得分:2)
从一致性的角度来看,数字2将始终返回2个数据集。除了重载之外,你不会有一个可能返回结果的客户端代码方法,也许不会。
如果您重复使用此代码,则另一个调用客户端也必须知道此标志。
如果代码执行了2个不同的操作,那为什么不会有2个不同的存储过程?
最后,使用现代JOIN语法并从过滤中单独加入是更好的做法。在这种情况下, personall 我也会使用EXISTS。
SELECT
D.*
FROM
Departments D
JOIN
Employees E ON D.DepartmentId = E.DepartmentId
WHERE
E.EmployeeId = @EmployeeId
AND
@IncludeDepartmentInfo = 1
答案 1 :(得分:1)
SELECT Departments.* FROM Departments, Employees
WHERE Departments.DepartmentId = Employees.DepartmentId
AND Employees.EmployeeId = @EmployeeId
AND @IncludeDepartmentInfo = 1
当SQL编译这样的查询时,必须为@IncludeDepartmentInfo的任何值编译它。生成的计划可以是扫描表并执行连接的计划,检查变量之后的,导致不必要的I / O.优化器可能是智能的,并且在执行计划中的实际I / O操作之前移动对变量的检查,但这绝不保证。这就是为什么我总是建议在T-SQL中使用显式IF来进行基于变量值需要执行非常不同的查询(典型的例子是OR条件)。
gbn的观察也很重要:从API设计的角度来看,最好有一致的返回类型(即总是返回相同形状和数量的结果集)。答案 2 :(得分:0)
使用'if'语句时,您可能只运行一个查询而不是两个查询。我认为一个查询几乎总是比两个快。如果第一个查询很复杂并且需要很长时间才能运行,那么关于查询计划的观点可能是有效的,而第二个查询是微不足道的。但是,第一个查询看起来像是基于主键检索单行 - 每次都可能非常快。所以,我会保留'if' - 但我会测试验证。
答案 3 :(得分:0)
性能差异太小,任何人都无法注意到。
Premature optimization is the root of all evil.不要担心性能问题并开始实施让客户微笑的功能。