问题与性能和最佳实践有关。(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)
是对每个条件都执行一次表扫描,还是无论有多少条件都只执行一次表扫描?处理这类逻辑的优雅方式是什么?由于
您的两个代码块在逻辑上不相等。我假设IF(result)
是指IF(@result > 0)
。在这种情况下,将返回您找到的第一个非零计数。在第二个代码块中,您将实际得到所有条件的所有计数的总和。
WITH RECOMPILE
指令来缓解一些问题。这在SQL 2005中有一些错误,但既然你在SQL 2008上,你应该没问题。
在第一个代码块中,SQL Server可以为每个查询设置单独的查询计划。
在任何情况下,哪一个实际上是最好的将取决于很多因素。你最好的办法是将它们与非常接近实际生产数据的测试数据并排测试。
同样,不要忘记代码的可维护性和可读性。如果这是不经常运行的代码,或者如果性能差异足够小,那么您可能最好使用最容易维护和理解的代码,特别是如果您有很多条件或可能经常更改它们。
最后,条件是否依赖于存储过程的参数?是否有些参数经常被忽略,暗示条件不相关?如果是这样,那么您应该非常仔细地阅读Erland Sommarskog撰写的关于动态搜索条件的文章。在一个客户端,我发现动态SQL是目前为止性能最好的方法对于这种情况,当然,当涉及到安全性时,必须非常小心地使这段代码密不透气。
最好在in子句中放置不同的条件,因为它只会制定一次计划,然后检查多个条件,但如果您将分别执行,它将不得不每次执行计划
很难说是否会进行完整扫描,这取决于数据的基数,以及是否有合适的索引。
假设每次选择都将完全扫描…
和WHERE子句是不同的,你必须将这个逻辑合并到select using CASE WHEN
中见:http://msdn.microsoft.com/en-us/library/aa258235 (v = sql.80) . aspx
则需要一个条件块来返回正确的值。
的好处是,这将只完整扫描一次。