问题涉及绩效和最佳实践。 (sql server 2008存储过程)
如果存储过程包含这样的代码
result = select count(*) from tableA where (some condition1)
if (result) -- meaning we got something from above query
return result
else
result = select count(*) from tableA where (some other condition2)
and so on until
result = select count(*) from tableA where (some other conditionN)
将所有条件放在像这样的大查询中是否更好
resultn = select count(*) from tableA
where (condition1 or condition1 or... conditionN)
是否会针对每种情况进行表扫描,或者无论有多少条件,都会进行一次表扫描。什么是处理这种逻辑的优雅方式。感谢
答案 0 :(得分:1)
最好在IN子句中加入不同的条件,因为它只会使其计划一次,然后检查多个条件,但如果你将执行seperaly,则每次都必须执行计划。
答案 1 :(得分:1)
无法确定是否会发生完整扫描,这取决于数据的基数,以及是否有合适的索引。
假设每个选择都将完全扫描......
并且您的WHERE子句不同,您必须使用CASE WHEN
将此逻辑合并到选择中请参阅:http://msdn.microsoft.com/en-us/library/aa258235(v=sql.80).aspx
然后你需要一个条件块来返回正确的值。
好处是这只会完全扫描一次。
答案 2 :(得分:1)
您的两个代码块在逻辑上不相同。我将假设IF(result)
确实意味着IF(@result > 0)
。在这种情况下,将返回您找到的第一个非零计数。在第二个代码块中,您实际上将获得所有条件的所有计数总数。
在第二个代码块中,SQL Server只能为查询选择一个查询计划。如果您的所有列都有索引,它仍然只能使用其中一个列。我不认为它将使用每个查询条件的索引进行并行处理。我没有专门测试过这个,所以如果我错了,也许有人可以纠正我。您可以通过在存储过程中使用WITH RECOMPILE
指令来缓解此问题。这在SQL 2005中有一些错误,但是因为你在SQL 2008上,你应该没问题。
在您的第一个代码块中,SQL Server可以为每个查询提供单独的查询计划。
在任何情况下,哪一个实际上最佳将取决于很多因素。您最好的选择是将测试数据与测试数据并排测试,这些数据非常类似于您的实际生产数据。
另外,不要忘记代码的可维护性和可读性。如果这是经常不运行的代码,或者性能差异足够小,那么最好使用最容易维护和理解的代码,特别是如果您有很多条件或者可能经常更改它们。
最后,条件是否依赖于存储过程的参数?是否会遗漏一些这些参数,暗示条件不相关?如果是这样,那么你应该仔细阅读Erland Sommarskog的article on dynamic search conditions。在一个客户端,我发现动态SQL是迄今为止性能最强的方法 ,但是当涉及到安全性时,当然需要非常小心地使这个代码变得密不透风。