下面是我的过程中的一条SELECT语句的简单版本:
select
...
from
...
where
((@SearchTextList IS NULL) OR
(SomeColumn IN (SELECT SomeRelatedColumn From #SearchTextListTable)))@SearchTextList只是一个保存逗号分隔的字符串列表的varchar变量。#SearchTextListTable是保存搜索文本值的单列临时表。
这个查询需要30秒才能完成,这是我的应用程序中的性能问题。
如果我去掉了第一个条件(即如果我去掉了OR条件),它只需要一秒钟。
select
...
from
...
where
SomeColumn IN (SELECT SomeRelatedColumn From #SearchTextListTable)有人能解释一下为什么会有这么大的差异吗?
SQL Server引擎内部发生了什么?
谢谢。
发布于 2015-08-04 03:57:23
既然您说过在没有指定OR的情况下SQL是快速的,那么我假设该表具有SomeColumn的索引,并且#SearchTextListTable中的行数很小。在这种情况下,SQL Server可以决定使用索引来搜索行。
如果指定了或子句,则查询如下所示:
((@SearchTextList IS NULL) OR
(SomeColumn IN (SELECT SomeRelatedColumn From #SearchTextListTable)))SQL Server无法创建使用索引的计划,因为这些计划已缓存,并且在@SearchTextList为NULL时也必须可用。
通常有两种方法可以改进这一点,要么使用动态SQL,要么为每次执行重新编译计划。
要重新编译计划,只需将option (recompile)添加到查询的末尾。除非这个查询真的经常执行,否则这应该是一个不错的解决方案。缺点是它会导致稍微高一点的CPU使用率,因为计划不能被重用。
另一种选择是创建动态SQL并使用sp_executesql执行它。因为在这一点上你知道@SearchTextList是否为NULL,所以你可以省略SomeColumn在...当它不需要的时候。注意这种情况下的SQL注入,不要仅仅将变量值连接到SQL字符串中,而是在SQL中使用变量,并将这些变量作为参数提供给sp_executesql。
如果SQL中只有这一列,您还可以为这两个选项创建两个单独的过程,并根据具体情况从原始过程执行它们。
https://stackoverflow.com/questions/31791408
复制相似问题