条件查询的性能注意事项(搜索表单)

Joh*_*ers 9 sql-server sql-server-2008

我经常发现存储过程的代码如下:

SELECT columns
FROM table_source
WHERE 
    (@Param1 IS NULL OR Column1 LIKE @Param1)
AND (@Param2 IS NULL OR Column2 = @Param2)
AND (@Param3 IS NULL OR ISNULL(Column3,'') LIKE @Param3 + '%')
…
Run Code Online (Sandbox Code Playgroud)

这有什么比这样的更好:

WHERE 
    (Column1 LIKE COALESCE(@Param1, Column1))
AND (Column2  = COALESCE(@Param2, Column2))
AND (ISNULL(Column3,'') LIKE COALESCE(@Param3 + '%', ISNULL(Column3, '')))
…
Run Code Online (Sandbox Code Playgroud)

如果我拉出仅依赖于参数的表达式,这是否重要?

DECLARE @Param3Search nvarchar(30);
SET @Param3Search = @Param3 + '%';
Run Code Online (Sandbox Code Playgroud)

那么用@Param3Search而不是@Param3

很抱歉问这么广泛,但我确信有一些一般的经验法则来编写这样的查询.我只是找不到一个现有的问题.

Mar*_*ith 4

有关此主题的权威文章链接自T-SQL 中的动态搜索条件

您的问题被标记为 SQL Server 2008。如果您至少使用 SP1 CU5,那么您可以利用“参数嵌入优化”行为作为动态 SQL 的替代方案。

SELECT columns
FROM   table_source
WHERE  ( @Param1 IS NULL
          OR Column1 LIKE @Param1 )
       AND ( @Param2 IS NULL
              OR Column2 = @Param2 )
       AND ( @Param3 IS NULL
              OR ISNULL(Column3, '') LIKE @Param3 + '%' )
OPTION (RECOMPILE); 
Run Code Online (Sandbox Code Playgroud)

将在每次调用时重新编译,并能够考虑该执行的实际变量/参数值。

暂时假设一切都是NOT NULL。该计划将编制为

SELECT columns
FROM   table_source
WHERE  Column1 LIKE @Param1
       AND Column2 = @Param2
       AND ISNULL(Column3, '') LIKE @Param3 + '%' 
Run Code Online (Sandbox Code Playgroud)

(我可能会看看扩展 Column3 上的谓词是否也会带来更好的计划)

现在假设它们都是 NULL。该计划应该简化为

SELECT columns
FROM   table_source
Run Code Online (Sandbox Code Playgroud)

这可能比动态 SQL 方法更易于维护,并且意味着缓存中可能的一次性计划更少,但确实会产生额外的重新编译开销。