質問に対するZaneのコメントで、彼は次のように述べています。
...問題の一部のように思えますが、プランで20Kを返すために5000万行を読み取っています。
これが実際に問題です。述部の一部またはすべてをストレージエンジンにプッシュするために使用できるインデックスがありません。マイクロソフトは、ドキュメントの記事「テンポラルテーブルの考慮事項と制限事項」にあるテンポラルテーブルのこのベースラインインデックス作成戦略を推奨しています。
最適なインデックス作成戦略には、現在のテーブルのクラスター化列ストアインデックスまたはBツリー行ストアインデックスと、最適なストレージサイズとパフォーマンスのための履歴テーブルのクラスター化列ストアインデックスが含まれます。独自の履歴テーブルを作成/使用する場合は、期間の終了列から始まる期間列で構成されるこのタイプのインデックスを作成して、一時的なクエリを高速化し、データの一貫性の一部であるクエリを高速化することを強くお勧めします小切手。デフォルトの履歴テーブルには、期間列(終了、開始)に基づいてクラスター化された行ストアインデックスが作成されます。少なくとも、非クラスター化行ストアインデックスをお勧めします
その言い回しは少し混乱します(とにかく私には)。ただし、重要な点は、これらのインデックスを作成してパフォーマンスを向上させることができるということです。
現在のテーブルのNCインデックスSysEndTime。
CREATE NONCLUSTERED INDEX IX_SysEndTime_SysStartTime
ON dbo.Benefits (SysEndTime, SysStartTime)
/*INCLUDE (ideally, include your other important fields here)*/;
これにより、適切な終了時刻を探すことにより、現在のテーブルの一部の行を読み取ることを回避できます。
履歴テーブルのCCI
CREATE CLUSTERED COLUMNSTORE INDEX ix_BenefitsHistory
ON dbo.BenefitsHistory
WITH (DROP_EXISTING = ON);
これにより、履歴テーブルでバッチモードを使用できるようになり、スキャンがはるかに高速になります。
現在のテーブルのNCインデックスSysStartTime。
日付範囲クエリのインデックス作成が難しい理由の詳細については、質問の日付範囲を取得する最も効率的な方法に対するPaulの回答を参照してください。そこでのロジックに基づいて、SysStartTimeで先行する現在のテーブルに別のNCインデックスを追加して、オプティマイザが統計とクエリの特定のパラメータに基づいて使用するNCインデックスを選択できるようにするのは理にかなっています。
CREATE NONCLUSTERED INDEX IX_SysStartTime_SysEndTime
ON dbo.Benefits (SysStartTime, SysEndTime)
/*INCLUDE (ideally, include your other important fields here)*/;
上記の3つのインデックスを作成すると、テストケースでのリソース使用量に大きな違いが生じました。合計150万行を返す2つのクエリを実行するテストケースを設定しました。履歴と現在のテーブルの両方に5,000万行あります)。
注:SSMSのオーバーヘッドを減らすために、「実行後に結果を破棄する」オプションを有効にしてテストを実行しました。
実行計画-デフォルトのインデックス
論理読み取り:1,330,612
CPU時間:00:00:14.718
経過時間:00:00:06.198
実行計画-上記のインデックスを使用
論理読み取り:27,656(8,111行ストア+ 19,545列ストア)
CPU時間:00:00:01.828
経過時間:00:00:01.150
ご覧のとおり、合計経過時間を含めて、3秒の測定すべてが6秒から1秒に大幅に減少しました。
ドキュメントの記事で提示されている他のオプションは、クラスター化列ストアインデックスを優先して、現在のテーブルの2つのNCインデックスを無視することです。私のテストでは、パフォーマンスは上記のインデックス作成ソリューションと非常に似ていました。