16

我已经和这个斗争了一段时间了。我有一个存储过程,它接受 3 个用于过滤的参数。如果传入了特定值,我想对其进行过滤。如果传入-1,全部给我。

我已经尝试了以下两种方法:

第一种方式:

SELECT field1, field2...etc  
FROM my_view  
WHERE  
parm1 = CASE WHEN @PARM1= -1 THEN parm1  ELSE @PARM1 END  
AND parm2 = CASE WHEN @PARM2 = -1 THEN parm2  ELSE @PARM2 END  
AND parm3 = CASE WHEN @PARM3 = -1 THEN parm3  ELSE @PARM3 END

第二种方式:

SELECT field1, field2...etc  
FROM my_view  
WHERE  
(@PARM1 = -1 OR parm1 = @PARM1)  
AND (@PARM2 = -1 OR parm2 = @PARM2)  
AND (@PARM3 = -1 OR parm3 = @PARM3)  

我在某处读到第二种方法会短路,如果为真,则永远不会评估第二部分。我的 DBA 说它强制进行表扫描。我尚未对此进行验证,但在某些情况下似乎运行速度较慢。

该视图从中选择的主表有大约 150 万条记录,并且该视图继续连接大约 15 个其他表以收集大量其他信息。

这两种方法都很慢......从即时到任何地方都需要 2-40 秒,这在我的情况下是完全不可接受的。

有没有更好的方法不涉及将其分解为特定 vs -1 的每个单独案例?

任何帮助表示赞赏。谢谢。

4

5 回答 5

6

我在某处读到第二种方法会短路,如果为真,则永远不会评估第二部分。我的 DBA 说它强制进行表扫描。

你读错了;它不会短路。你的 DBA 是对的;它不能很好地与查询优化器配合使用,并且可能会强制进行表扫描。

第一个选项几乎与它一样好。改进的选项是动态 sql 或具有过滤列的所有可能组合的长存储过程,以便您获得独立的查询计划。您也可以尝试使用“WITH RECOMPILE”选项,但我认为它不会对您有所帮助。

于 2009-10-08T19:15:06.613 回答
5

如果您运行的是 SQL Server 2005 或更高版本,则可以使用 IF 使用适当的 WHERE 生成多个版本的查询,以便可以使用索引。每个查询计划都将放在查询缓存中。

另外,这里有一篇关于这个主题的非常全面的文章:

Erland Sommarskog 在 T-SQL 中的动态搜索条件

它涵盖了尝试使用多个可选搜索条件编写查询的所有问题和方法

这是目录:

  介绍
      案例研究:搜索订单
      北风数据库
   动态 SQL
      介绍
      使用 sp_executesql
      使用 CLR
      使用 EXEC()
      当缓存不是你真正想要的
   静态 SQL
      介绍
      x = @x 或 @x 为空
      使用 IF 语句
      乌马昌达的诡计袋
      使用临时表
      x = @x AND @x 不为空
      处理复杂条件
   混合解决方案——同时使用静态和动态 SQL
      使用视图
      使用内联表函数
   结论
   反馈和致谢
   修订记录
于 2009-10-08T19:19:56.683 回答
2

如果在需要所有内容时传入空值,则可以将 where 子句编写为

   Where colName = IsNull(@Paramater, ColName)  

这与您的第一种方法基本相同...只要列本身不可为空,它就可以工作...列中的空值会稍微弄乱它

加快它的唯一方法是在 Where 子句中被过滤的列上添加一个索引。已经有了吗?如果没有,那将导致显着的改善。

于 2009-10-08T19:17:11.680 回答
0

我想不出其他办法:

在哪里

(MyCase 为 NULL 或 MyCase = @MyCaseParameter) AND ....

如果你问我,第二个对他们的开发人员来说更简单、更易读。

于 2009-10-08T19:13:59.317 回答
0

SQL 2008 及更高版本对优化进行了一些改进,例如(MyCase IS NULL OR MyCase = @MyCaseParameter) AND ....

如果您可以升级,并且添加一个OPTION (RECOMPILE)以获得所有可能的参数组合的良好性能(在这种情况下,没有适合所有可能的参数组合的单一计划),您可能会发现这表现良好。

http://blogs.msdn.com/b/bartd/archive/2009/05/03/sometimes-the-simplest-solution-isn-t-the-best-solution-the-all-in-one-search-查询.aspx

于 2011-03-03T17:09:23.640 回答