インデックス付きビューの理想的なシナリオのように聞こえます。これにより、クエリ時間ではなく書き込み時間に計算と集計の料金を支払うことができます。
CREATE VIEW dbo.MyIndexedView
WITH SCHEMABINDING
AS
SELECT Enroll_Date, UserID, RawCount = COUNT_BIG(*)
FROM dbo.UserTable
GROUP BY Enroll_Date, UserID;
GO
CREATE UNIQUE CLUSTERED INDEX CIX_miv ON dbo.MyIndexedView(Enroll_Date, UserID);
これを作成するには時間がかかります。もちろん、ベーステーブルのインデックスと同じように、すべてのDML操作全体でメンテナンスが必要になります。
これで、このビューに対するクエリは非常によく似たものになります。ビューの各行は個別のユーザー/日付の組み合わせを表すため、ベーステーブルの行の総数は1であるCOUNT(*)で計算できます。すでに部分的に集計されていますが、日付ごとのSUMを使用してそれらを追加するだけです。
SELECT Enroll_Date,
[Record #] = SUM(RawCount),
[User #] = COUNT(*)
FROM dbo.MyIndexedView WITH (NOEXPAND)
GROUP BY Enroll_Date;
これとthisを思い出した後、NOEXPANDヒントを追加しました。
このクエリが現在のクエリよりも高速であることは間違いありません(ただし、その程度ではありません)。ただし、日付ごとに正確に1人のユーザーがいるというまれなケース(この場合、同じ量のデータには読み取り)と私たちが知っている列は、ベーステーブルのインデックス内の唯一の列です。読み取り時のパフォーマンスの向上が、ワークロードの書き込み部分に影響を与える余分な作業に見合うかどうかは、私たちには言えません-トレードオフを測定するためにテストする必要があります(インデックスは無料です)。
また、特定の明確に定義された範囲(たとえば、現在の四半期または年初から現在まで)に対してEnroll_Dateに対して同じ共通のWHERE句を頻繁に使用する場合は、I / Oをさらに削減する一致するフィルター処理されたインデックスを追加できます(ただし、常にトレード・オフ)。
また、クラスター化インデックスをベーステーブルに配置することも検討してください。これは、ヒープの恩恵を受ける非常にまれなユースケースの1つではないようです。