在SQL中添加额外的Where子句会带来巨大的性能损失

时间:2011-01-20 21:04:59

标签: sql sql-server tsql sql-server-2000

我有一个运行多个视图和表格的SQL查询。

查询运行正常,但是当我在WHERE子句中添加另一个条件时,它开始对性能产生巨大影响。

查询的结构类似于......

         SELECT a.*
           FROM vw_myView a
LEFT OUTER JOIN tbl1 b ON a.ID = b.ID
LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID
LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID
          WHERE a.Column1 = 'VALUE'
            AND a.Column2 LIKE ISNULL(@parameter, a.Column2)

从上面的查询中,当我在WHERE子句中添加其他条件时,我的查询现在需要花费大量时间(超过3分钟)来执行并返回1000条记录。删除添加的条件子句和查询会在不到7秒的时间内返回记录。

感谢。 我应该检查什么才能看到性能影响巨大

5 个答案:

答案 0 :(得分:1)

查看您的查询execution plan。我敢向甜甜圈打赌,你的额外搜索参数导致了表扫描,这是一个非常昂贵的程序,性能方面。

答案 1 :(得分:0)

为什么这样? AND a.Column2 LIKE ISNULL(NULL, a.Column2)
这总是要检查a.Column2 LIKE a.Column2
您是否只想查看a.Column2 IS NULL

您可以在修改之前发布查询吗?

[编辑]
我不知道您的目标数据库,但如果是Sybase,我会提醒您不要使用@parameter + '%'进行表扫描。您可以在To LIKE or not to LIKE了解更多信息。

答案 2 :(得分:0)

您的查询子句AND a.Column2 LIKE ISNULL(@parameter, a.Column2)涉及调用函数,因此SQL Server必须执行表扫描(即测试该函数对每个行)表,看它是否满足查询。

即使你在a.Column2上有索引,Sql Server也无法使用它。

[编辑]这是在大多数情况下加快速度的一种方法

-- Only this part executes when the @parameter has a value.
-- It returns nothing and executes fast when @parameter is NULL

SELECT a.*
           FROM vw_myView a
LEFT OUTER JOIN tbl1 b ON a.ID = b.ID
LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID
LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID
          WHERE a.Column1 = 'VALUE'
            AND a.Column2 LIKE @parameter

UNION ALL

-- This part does not execute when the @paramter has a value
-- This will leave the 2nd query clause out and run faster when @parameter is not specified, avoiding a table scan

SELECT a.*
           FROM vw_myView a
LEFT OUTER JOIN tbl1 b ON a.ID = b.ID
LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID
LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID
          WHERE a.Column1 = 'VALUE'
            AND @parameter IS NULL

答案 3 :(得分:0)

动态SQL可能是您最好的选择。如果参数为null,则创建一个语句;如果参数不为,则创建不同的语句。这是通过大量可能的参数更快地进行搜索的常用方法。

由于你只有两个条件,我可能会尝试这样写: IF @parameter IS NULL

BEGIN
    SELECT a.*            
    FROM vw_myView a 
    LEFT OUTER JOIN tbl1 b 
    ON a.ID = b.ID 
    LEFT OUTER JOIN vw_OtherView c 
    ON a.ID = c.ID 
    LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID           
    WHERE a.Column1 = 'VALUE'             
    AND a.Column2 LIKE a.Column2 
END
ELSE 
BEGIN
    SELECT a.*            
    FROM vw_myView a 
    LEFT OUTER JOIN tbl1 b 
    ON a.ID = b.ID 
    LEFT OUTER JOIN vw_OtherView c 
    ON a.ID = c.ID 
    LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID           
    WHERE a.Column1 = 'VALUE'             
    AND a.Column2 LIKE  @parameter
END

当然,您不应该在生产代码中使用SELECT *,如果可能,请使用=而不是LIKE。如果这些视图引用相同的表,则直接查询表可能是性能的更好选择。

答案 4 :(得分:0)

试试这个。

AND (a.Column2 = @parameter OR @parameter is NULL)

不明白为什么你这样使用?

你想做这样的事吗

AND (a.Column2 like @parameter+'%' OR @parameter is NULL)