SQL Server存储过程 - 'IF语句'与'Where标准'

时间:2009-11-27 14:36:16

标签: sql-server tsql query-optimization

在很长一段时间内沸腾的问题,在以下两个存储过程中,哪一个会表现得更好。

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'及其差异的两种情况下),我知道有很多方面可能影响我在这个问题中要避免的性能。

4 个答案:

答案 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.不要担心性能问题并开始实施让客户微笑的功能。