1

考虑以下数据表:

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

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

考虑到要过滤的大量 PersonId,如何提高性能?

更新

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

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

  • 过滤单个 PersonId:100ms
  • 完全没有过滤器:750 毫秒
  • 过滤 1500 个 PersonId:2300 毫秒

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

4

3 回答 3

0

难道大部分时间实际上都花在了“group by”子句上吗?

看看执行计划就知道了。

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

于 2012-06-20T03:19:58.693 回答
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;
于 2012-06-19T21:03:53.160 回答
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

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

于 2012-06-19T21:07:09.227 回答