Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server存储过程-';IF语句';vs';其中标准';_Sql Server_Tsql_Query Optimization - Fatal编程技术网

Sql server SQL Server存储过程-';IF语句';vs';其中标准';

Sql server SQL Server存储过程-';IF语句';vs';其中标准';,sql-server,tsql,query-optimization,Sql Server,Tsql,Query Optimization,这个问题在我脑海中酝酿了很长一段时间,在下面两个存储过程中,哪一个性能更好 程序1 CREATE PROCEDURE GetEmployeeDetails @EmployeeId uniqueidentifier, @IncludeDepartmentInfo bit AS BEGIN SELECT * FROM Employees WHERE Employees.EmployeeId = @EmployeeId IF (@IncludeDepartmentInf

这个问题在我脑海中酝酿了很长一段时间,在下面两个存储过程中,哪一个性能更好

程序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
程序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”两种情况下以及它们之间的差异)非常特别,我知道有许多方面可能会影响性能,我想在这个问题中避免这些方面。

当您使用“if”语句时,您可能只运行一个查询,而不是两个查询。我认为一个查询几乎总是比两个查询快。如果第一个查询很复杂,运行时间很长,而第二个查询很琐碎,那么您关于查询计划的观点可能是有效的。但是,第一个查询看起来像是基于主键检索一行,每次可能都非常快。因此,我会保留“if”-但我会测试以验证。

性能差异太小,任何人都不会注意到


停止担心性能,开始实施让客户微笑的功能。

从一致性的角度来看,第2项总是返回2个数据集。撇开重载不谈,您不会有一个可能返回结果的客户机代码方法,也可能不会

如果重用此代码,则其他调用客户端也必须知道此标志

如果代码执行两种不同的操作,那么为什么不执行两种不同的存储过程呢

最后,使用现代连接语法并将连接与过滤分离是更好的做法。在这种情况下,我个人也会使用

SELECT
    D.*
FROM
    Departments D
    JOIN
    Employees E ON D.DepartmentId = E.DepartmentId
WHERE  
    E.EmployeeId = @EmployeeId 
    AND
    @IncludeDepartmentInfo = 1
当SQL编译这样的查询时,它必须针对@IncludeDepartmentInfo的任何值进行编译。生成的计划很可能是扫描表并执行连接,然后检查变量,从而导致不必要的I/O。优化器可能很聪明,在执行计划中将变量检查提前于实际I/O操作,但这永远无法保证。这就是为什么我总是建议在T-SQL中使用显式IFs来处理需要根据变量值执行非常不同的查询的原因(典型的示例是OR条件)


gbn的观察结果也很重要:从API设计的角度来看,具有一致的返回类型(即始终返回相同形状和数量的结果集)更好

本质上,第一个查询可能返回当前示例中没有的多个记录,第二个查询也是可选的,在proc 2中,SQL查询优化器本身将首先匹配常量条件,如果不匹配,则不会进行更多的条件匹配。同样,这些只是我对SQL查询优化器的假设。真正了解的唯一方法是对真实的实时数据进行测试,看看会发生什么。Andomar的观点是很好的——在大多数情况下,差异太小,不必担心。我理解你的意思,但这句话似乎可以作为借口,类似于“我的代码是自文档化的,所以我不需要创建文档。”:)聪明并不意味着你不能问基本的问题,我同意过早选择是所有罪恶的根源,但这并不意味着我们不应该从一开始就写得更好。有些系统的这一点性能改进很重要。我知道我们可以使用两个存储过程,还有一个优雅的join语句(用join替换老式的查询),但我的简单问题是,这两个语句中哪一个性能更好?@scorpio:这取决于:小表还是宽表?大结果还是小结果?计划不确定性的开销将超过不发送一小部分数据的任何优势。题外话:使用两个存储过程最好是使用两个表函数。gbn感谢您的回复。从客户端代码看,我认为proc2将一致地返回两个结果集,这取决于第二个结果集是否为空。在这种情况下,当包含超过100k条记录的表再次返回1000条记录时,哪个过程会更好?我有一个实际的场景,其中数据库表有大量超过10列的记录,我只是通过尝试给出一个简单的例子来提问。@scorpio:我有两个存储过程。根据Remus,如果在WHERE中,第二个查询仍然可以进行评估。IF更改签名
SELECT Departments.* FROM Departments, Employees
    WHERE Departments.DepartmentId = Employees.DepartmentId 
    AND Employees.EmployeeId = @EmployeeId 
    AND @IncludeDepartmentInfo = 1