1

次のデータ テーブルを検討してください。

CREATE TABLE Person
(
    PersonId int PRIMARY KEY
)

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

このようなクエリを実行すると、DateKey でグループ化された Fact1 が集計されます

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 を指定して、パフォーマンスを改善するにはどうすればよいですか?

アップデート

上記の例は私のデータ構造を単純化したものですが、正確に例えることができれば幸いです。

約 3,200 万行の PersonData と 2,000 人の一意の人物が与えられた場合のクエリと時間の影響の例:

  • 1 つの PersonId でのフィルタリング: 100 ミリ秒
  • フィルターなし: 750 ミリ秒
  • 1500 個の PersonId のフィルタリング: 2300 ミリ秒

注: すべてのクエリについて、DateKey (日付ディメンション テーブルへの外部キー) を 1 か月の期間に制限する WHERE 句も実行しています。

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 に答える