2017-07-27 186 views
1

我在我们的数据库DB中有一个60亿行的表,这基本上是几年内发生的所有事务。这有ColumnStore索引,其中包含所有列,并且没有其他索引。有一个用户界面,用户将提供多个搜索条件(比如基于日期/金额/支付类型)等,我必须查询此表并返回TOP 1000结果。SQL Server动态WHERE子句

我已经通过了以下建议的各种帖子。

  1. 使用具有各种if条件的变量并动态构建sql。使用sp_executesql的 - 的SQL变得非常混乱与所有这些逻辑

  2. 使用CoalesceIsNullCASEWHERE条款 - 这看起来简洁,但非常缓慢。例如WHERE Total = 10需要(1秒),而Total = Coalesce(@Total, Total)需要几分钟才能运行。相同的延迟与IsNullCASE

我只是想确认是否有没有其他办法可以做到动态SQL除了上述2点的方法?欣赏你的想法。谢谢!

+4

这通常称为“全部通过”查询。它们在搜索和其他用途中非常常见。这里有一篇关于这个主题的伟大文章,讨论了使这些工作快速完成的几个选项。 http://www.sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/ –

+2

Gail Shaw的另一篇文章... https://www.red-gate.com/simple-talk/sql/t-sql-programming/how-to-confuse-the-sql-server-query-optimizer/ –

回答

0

这可能证明更有效。

WHERE 
    ((@Total IS NULL) OR ([email protected])) 
    AND 
    ((@Param2 IS NULL) OR ([email protected])) 
+1

“WHERE Total = @Total”需要1秒,因为“WHERE(((@Total IS NULL )OR(Total = @ Total))“需要8秒 – user2980765

+0

最有可能出于同样的原因您的原始查询是慢....参数嗅探。在这种情况下,首先编译和缓存的任何代码将是最快的 –

+0

是的,OPTION(RECOMPILE)几乎可以避免搜索过程中的异常延迟。 –

0

另一种方法是这样的。

where Field1 = @aMandatoryParameter 
and (Field2 = @optionalPameter or @inputPameter is null) 
1

你在做什么通常被称为“捕获所有查询”......有几种方法可以解决这个问题。

1)动态SQL是一个有效的选项,但可能会超过kill。 2)可以工作,只要确保您添加选项(重新)和查询结束。

你从1秒变为几分钟的原因是因为你从索引查找转到索引扫描... OPTION(重新编译)将允许优化器选择查找计划。

+0

添加OPTION(RECOMPILE)与((@Total IS NULL)OR(Total = @ Total))使动态WHERE不同。谢谢! – user2980765

+0

不客气。 :) –