【问题标题】: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 秒。
任何如何解决问题的信息将不胜感激。
【问题讨论】:
标签:
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,那么您的意思是它是正确的,并且不需要评估您的第二个过滤器,从而使您的查询更快。