加速使用WHERE IN进行过滤的动态SQL查询

时间:2012-06-19 20:30:01

标签: performance tsql join

考虑以下数据表:

CREATE TABLE Person
(
    PersonId int PRIMARY KEY
)

CREATE TABLE PersonData 
(
    PersonId int, -- with foreign key to person table
    DateKey Date,
    Fact1 int,
)

我可以执行这样的查询,它将聚合Fact1,按DateKey

分组
SELECT DateKey, SUM(Fact1) 
FROM PersonData
GROUP BY DateKey

现在让我们假设我想按personId过滤并显示id为1 2和3的人的数据。我可以这样做:

SELECT DateKey, SUM(Fact1) 
FROM PersonData
WHERE PersonId IN (1, 2, 3)
GROUP BY DateKey

如果我分崩离析,如果我有大量的personIds,我想要过滤它。即WHERE T2.PersonId IN(1,2,3,4,5 ... 1000 +)

如果要过滤大量的PersonId,我如何才能提高性能?

更新

虽然上面的例子简化了我的数据结构,但希望它是一个准确的类比。

示例查询和时间影响,给出大约3200万行PersonData和2000个唯一人:

  • 过滤单个PersonId:100毫秒
  • 根本没有过滤器:750毫秒
  • 过滤1500人: 2300毫秒

注意:对于所有查询,我还执行WHERE子句将DateKey(日期维度表的外键)限制为1个月的时间。

3 个答案:

答案 0 :(得分:0)

试试这个:

declare @beginValue int = 1,
        @endValue int = 87;

--Only work if you need a interval of numbers (example: 1 to 87, in Person table)
SELECT pdt.DateKey, SUM(pdt.Fact1)
FROM PersonData AS pdt
     INNER JOIN Person AS per ON pdt.PersonId = per.PersonId
WHERE per.PersonId BETWEEN @beginValue AND @endValue
GROUP BY pdt.DateKey;

答案 1 :(得分:0)

您可以尝试将所有PersonID加载到SQL中的表中。然后使用:

SELECT DateKey, SUM(Fact1) 
FROM PersonData D
WHERE exists (SELECT 1 from PersonIDTable I where d.PersonID = I.PersonID)
GROUP BY DateKey

这通常会使查询运行得更快!

答案 2 :(得分:0)

可能是因为很大一部分时间实际上花在'group by'条款中了吗?

查看要执行的执行计划。

我想知道增加人员ID列表是否实际上导致DateKey排序成本线性增加。如果是这样,请在DateKey列上添加索引。