我有一个类似这样的存储过程(伪代码)
storedprocedure param1, param2, param3, param4
begin
if (param4 = 'Y')
begin
select * from SOME_VIEW order by somecolumn
end
else if (param1 is null)
begin
select * from SOME_VIEW
where (param2 is null or param2 = SOME_VIEW.Somecolumn2)
and (param3 is null or param3 = SOME_VIEW.SomeColumn3)
order by somecolumn
end
else
select somethingcompletelydifferent
end
很长一段时间都很顺利。突然,如果param4为'Y',则查询开始永远运行。将代码更改为:
storedprocedure param1, param2, param3, param4
begin
if (param4 = 'Y')
begin
set param2 = null
set param3 = null
end
if (param1 is null)
begin
select * from SOME_VIEW
where (param2 is null or param2 = SOME_VIEW.Somecolumn2)
and (param3 is null or param3 = SOME_VIEW.SomeColumn3)
order by somecolumn
end
else
select somethingcompletelydifferent
它会在预期的参数范围内再次运行(对于40,000多条记录,大约需要15秒)。这是SQL Server 2005.我的问题的要点是特定于SQL Server的这个特殊“功能”,或者这是RDBMS中的一般特征:
这可能看起来像对SQL Server的咆哮,我想在某种程度上它是,但我真的想知道其他人是否经历过Oracle,DB2或任何其他RDBMS的这种现实。虽然我对其他人有一些经验,但我只看到SQL Server上的这种数量和复杂性,所以我很好奇其他拥有大型复杂数据库的人在其他产品上有类似的经验。
答案 0 :(得分:4)
可能有几个原因
1)是最新的统计数据吗?
2)你可能会遭受参数嗅探
对于这种东西,顺便说一句其中(param2为null或param2 = SOME_VIEW.Somecolumn2)
查看Do you use Column=@Param OR @Param IS NULL in your WHERE clause? Don't, it doesn't perform
答案 1 :(得分:1)
我会想象这个问题的具体实例,导致这种情况发生的所有条件都是特定于SQL服务器的 - 甚至可能是版本。 (例如,SQL Server 2008的行为会有所不同。)
但这是查询优化器的一般“功能”。他们会查看您的查询,并尝试对最快执行的内容做出明智的猜测。作为用户,如果优化器选择(比方说)索引扫描或索引搜索,我们几乎没有直接控制,但可以通过提供表达相同事物的替代方式间接地影响它,以查看是否调用了改进的执行时间。
如果没有可能影响查询的任何其他架构更改,请检查索引统计信息是否已更新。我们使用每周批处理作业来完成此任务。