我有一个带可选参数的参数化查询。 连接多个表。 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?我想避免后者,因为
答案 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)
,这将花费时间来评估实际参数,但需要付出一定代价。
要回答您的问题“是否有办法重写上述声明,以便执行计划能够达到最佳效果?”,答案可能不是。有太多的变化可以提出一个单一的计划,有很多事情可能不会发生(你的空变量)。