Sql server SQL Server存储过程-';IF语句';vs';其中标准';
这个问题在我脑海中酝酿了很长一段时间,在下面两个存储过程中,哪一个性能更好 程序1Sql 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
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