将可选参数最佳传递到查询中

时间:2015-04-26 13:24:46

标签: sql-server sql-server-2008-r2

我有一个带可选参数的参数化查询。 连接多个表。 WHERE子句的一部分如下所示:

and ((x.a = @arg1) OR (@arg1 IS NULL))
and ((y.b = @arg2) OR (@arg2 IS NULL))
and ((z.c = @arg3) OR (@arg3 IS NULL))

因此,我们的想法是:一个参数可以用于应用过滤器,或者,如果参数为NULL,则不会应用过滤。

但是,我发现执行计划对此代码不利。 当实际设置参数时,写入

会好得多
and x.a = @arg1

而不是

and ((x.a= @arg1) OR (@arg1 IS NULL))

实际上,我总共有8张桌子连在一起。在两个语句中,所有8个表都已连接,并且在所有这些表上应用了相同的索引搜索/扫描。但是,连接顺序不同,从而导致执行速度不同。

有没有办法重写上述语句,以便执行计划能够达到最佳效果?可能有一些查询提示?

或者没有办法编写动态SQL?我想避免后者,因为

  • 动态SQL难以阅读,
  • SSMS不显示依赖关系,
  • 将参数传递给动态SQL很糟糕

2 个答案:

答案 0 :(得分:0)

尝试使用COALESCE(@arg1, x.a)代替((x.a = @arg1) OR (@arg1 IS NULL))

and x.a = COALESCE(@arg1, x.a)
and y.b = COALESCE(@arg2, xyb)
and z.c = COALESCE(@arg3, z.c)

答案 1 :(得分:0)

不幸的是,优化者倾向于坚持适合第一次调用的任何计划。您最好的选择是为每个组合(或至少是主要组合)编写存储过程或尝试OPTION(RECOMPILE),这将花费时间来评估实际参数,但需要付出一定代价。

要回答您的问题“是否有办法重写上述声明,以便执行计划能够达到最佳效果?”,答案可能不是。有太多的变化可以提出一个单一的计划,有很多事情可能不会发生(你的空变量)。