1

我正在使用 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)
    )

此查询执行很长时间。

但如果我@Param11, 替换查询执行时间约为 2 秒。

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

4

3 回答 3

1

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

于 2012-11-05T14:08:37.337 回答
0

您似乎将优化器与您的 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
于 2012-11-05T14:11:19.567 回答
0

这通常被称为 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
于 2012-11-05T14:14:07.687 回答