【问题标题】:How to improve performance of SQL query with parameters?如何提高带参数的 SQL 查询的性能?
【发布时间】:2012-10-25 09:09:15
【问题描述】:

我使用的是 SQL Server 2005。

我在执行这样的 SQL 语句时遇到问题

DECLARE @Param1 BIT
SET @Param1 = 1

SELECT 
    t1.Col1,
    t1.Col2
FROM
    Table1 t1
WHERE
    @Param1=0 OR
    (t1.Col2 in 
        (SELECT  t2.Col4
            FROM 
                Table2 t2
            WHERE 
                t2.Col1 = t1.Col1 AND 
                t2.Col2 = 'AAA' AND 
                t2.t3 <> 0)
    )

这个查询执行的时间很长。

但如果我将@Param1 替换为1,则查询执行时间约为2 秒。

任何如何解决问题的信息将不胜感激。

【问题讨论】:

  • 请贴出实际执行计划的XML版本。

标签: sql sql-server select parameters where-clause


【解决方案1】:

这通常被称为 N+1 问题。
您正在表 1 中进行选择,对于找到的每条记录,您都将在表 2 中查找内容。
通过将您的 @Param1 设置为在您的选择中永远找不到的值,sql 引擎将跳过子查询。
为了避免这种行为,您可以使用 JOIN 语句将两个表连接在一起,然后使用 where 语句过滤结果。连接语句会比单个子查询慢一点,因为您将 2 个表相互匹配,但因为您只需要执行一次连接(而不是 N 次),您将获得显着的性能提升。
示例代码:

DECLARE @Param1 BIT
SET @Param1 = 1

SELECT t1.Col1,t1.Col2
FROM Table1 t1
INNER JOIN Table2 t2 on t1.Col1 = t2.Col1
WHERE @Param1=0 
OR t2.Col2 = 'AAA' 
AND t2.t3 <> 0

【讨论】:

    【解决方案2】:

    您似乎将优化器与您的 OR 语句混淆了。如果你删除它,你会发现它会为 SELECT 语句生成两种不同的执行计划——一个带有过滤器,另一个没有:

    DECLARE @Param1 BIT
    SET @Param1 = 1
    
    if @Param1=0
    begin
        SELECT 
            t1.Col1,
            t1.Col2
        FROM
            Table1 t1
    end
    else
    begin
        SELECT 
            t1.Col1,
            t1.Col2
        FROM
            Table1 t1
        WHERE
            (t1.Col2 in 
                (SELECT  t2.Col4
                    FROM 
                        Table2 t2
                    WHERE 
                        t2.Col1 = t1.Col1 AND 
                        t2.Col2 = 'AAA' AND 
                        t2.t3 <> 0)
            )
    end
    

    【讨论】:

      【解决方案3】:

      嗯,解释似乎很简单。对于您当前的条件,由于 @Param1=0 为 false(您之前将参数设置为 1),它需要评估您的第二个条件,它有一个子查询并且可能需要很长时间。如果您将第一个过滤器更改为@Param1=1,那么您的意思是它是正确的,并且不需要评估您的第二个过滤器,从而使您的查询更快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-24
        • 2016-01-17
        • 1970-01-01
        • 2017-05-26
        • 1970-01-01
        • 2020-09-17
        相关资源
        最近更新 更多