具有大量IN参数的SQL查询很慢

时间:2016-03-23 10:36:27

标签: sql-server performance

我正在执行一些查询,其中包含在" IN"中指定的许多值。条款,像这样:

SELECT 
    [time_taken], [distance], [from_location_geocode_id],
    [to_location_geocode_id] 
FROM 
    [Travel_Matrix] 
WHERE 
    [from_location_geocode_id] IN (@param1, @param2, @param3, @param4, @param5) 
    AND [to_location_geocode_id] IN (@param1, @param2, @param3, @param4, @param5)

该示例显示了5个参数,但实际上可能有数百个参数。

对于少量参数(最多约400个),SQL Server使用具有多个"计算标量的执行计划"然后连接,排序和连接操作,以便返回结果。

对于大量参数(超过400),它使用"哈希匹配(右半连接)"方法,这更快。

但是,我希望它能更早地使用第二个执行计划,例如对于具有50个参数的查询,因为我的测试显示具有50-400个参数的查询往往变得非常慢。

我尝试过使用各种" OPTION"我的查询的值,但无法使用第二个执行计划执行它,我知道这将更有效。

我很感激能够建议如何为查询提供正确提示的人,以便它以第二个执行计划的方式执行。

由于

3 个答案:

答案 0 :(得分:4)

我认为使用IN子句的400个参数太多了。最好将这些值存储在临时表中并对其进行JOIN,也可以使用临时表的列上的索引来加快速度。

答案 1 :(得分:1)

在Performance透视中IN子句不好,请尝试下面这样的事情

DECLARE @Tmp TABLE(Id INT)
INSERT INTO @Tmp(Id) VALUES(@param1), (@param2), (@param3), (@param4), (@param5)

SELECT 
   [time_taken], [distance], [from_location_geocode_id],
   [to_location_geocode_id] 
FROM 
[Travel_Matrix] 
WHERE 
EXISTS (SELECT 1 FROM @Tmp Where @Tmp.Id=[from_location_geocode_id])
AND EXISTS (SELECT 1 FROM @Tmp Where @Tmp.Id=[to_location_geocode_id])

答案 2 :(得分:0)

您还可以使用这些参数创建过滤索引,即使您具有专门覆盖所有列值的索引。使用过滤索引,您的查询也会快得多。但是插入的速度会慢一些,过滤后的索引特别适合您的目的。

Ex:
create table test
(
id int
)

insert into test
select top 100* from numbers
where n<=1100

现在,如果我们的查询总是带有大参数,则说明为(2,100,45,98 ...)

中的id

如果我们创建一个过滤索引,如下所示

create index on dbo.test(id)
where id in (2,958,100)

我们的查询将使用该索引并且速度会快得多,当然在查询,案例查询,插入速度较慢之间存在一些限制。但我建议测试此选项并使其覆盖

<强>更新
进一步的统计是估计行值的关键,如果你没有带有fromlcoationid和tolcoationid作为关键列的索引,sql将不会创建多列stats.So还有一个选项是创建多列统计数据,如果你不想使用过滤索引方法...

create statistics test1 on dbo.test(fromlocationid,tolcoationid)
where fromlocationid in (@param1,.....) and tolocationid in (@param1,@param2...)

只有问题我看到过滤统计数据,与普通统计数据相比,它们不会如此频繁地更新。 所以你可能想尝试根据你的需要通过工作手动更新它们