Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 将可选参数最优地传递到查询中_Sql Server_Sql Server 2008 R2 - Fatal编程技术网

Sql server 将可选参数最优地传递到查询中

Sql server 将可选参数最优地传递到查询中,sql-server,sql-server-2008-r2,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

我有一个带有可选参数的参数化查询。 多个表被联接。 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非常糟糕
尝试使用
合并(@arg1,x.a)
而不是
((x.a=@arg1)或(@arg1为空))


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


要回答您关于“是否有方法重写上述语句,以使执行计划能够最佳工作?”的问题,答案可能不是。有太多的变化,不可能想出一个单一的计划,有这么多可能不会发生的事情(你的空变量)

好主意,但结果是一样的:(那么我猜,
x.a=CASE当@arg1为NULL时,那么x.a ELSE@arg1 END
也不会有帮助,但值得一试。你能发布执行计划吗?不管你做什么,动态sql都应该被视为最后的手段。是的,
CASE当
时,结果是一样的。实际语句连接了8个表,因此执行计划是big.将尝试以某种方式发布。在这两种情况下,所有8个表都被联接,并且在所有这些表上应用了完全相同的索引查找/扫描。但是,联接顺序不同,因此导致执行速度不同。很难优化您一无所知的查询。是的,
选项(重新编译)
很好!与
合并
变体[@ZoharPeled]结合使用,它会产生与手写变体相同的执行计划。这是一个缺点,仅重新编译时间会花费大约70毫秒的额外时间。因此,我将在这里坚持所有答案的组合。从性能角度来看,动态SQL是此任务的最佳解决方案。尽管您对依赖关系的看法是正确的,但不难理解阅读是否遵循了良好的编码实践。我不确定我是否理解传递参数的困难。传递到DynSQL的参数并不是很难,我只是不喜欢通过为每个“外部”创建一个“内部”参数将每个参数“隧道”到DynSQL的方式参数,然后将整个过程传递到exec函数中。但是很好。;)您可以在传递给sp_executesql的声明字符串中声明所有
内部
参数,并无条件映射
内部/外部
参数值。性能的关键是有条件地构建WHERE子句,以便只指定搜索实际需要的谓词。
and x.a = COALESCE(@arg1, x.a)
and y.b = COALESCE(@arg2, xyb)
and z.c = COALESCE(@arg3, z.c)