web-dev-qa-db-ja.com

インデックス付きビューを使用した最後の追跡のベストプラクティスを設計する

私のテーブル構造は以下の通りです:

_  TbDoc (ID int , ...)
  TbDocActions( ID Int, DocID Int, Date DateTime, col1 int, col2 int, ...)
_

TbDocレコードの最後のTbDocActions列を取得するためのインデックス付きビューが必要です。このビューの結果は以下のようになる必要があります。

_  DocID , col1, col2, ...
_

ビューでこの結果を取得するには、以下のクエリを使用できます。

_Select Z.DocID, X.*
From (Select DocID, Max(ID) as MaxActionID
      From TbDocActions
      Group By DocID
     )Z
inner join TbDocActions X ON X.ID = Z.MaxActionID
_

しかし、インデックス付きビューのパフォーマンスを向上させたいです。インデックス付きビューでは、Max()集約関数を使用できません。

5
mehdi lotfi

最速のソリューションは次のとおりです。追加の列IsLastIDを作成し、それを使用してフィルター処理されたインデックスまたはインデックス付きビューを作成します。 ここで説明 のように、IsLastIDの整合性を確保するために制約を使用できます。

Grant Fritcheyは、さまざまなソリューションの詳細な比較を書きました ここ

4
A-K

すでにご存じのとおり、インデックス付きビューではMAX()集計を使用できません。いずれにせよ、インデックス付きビューの作成は不思議なパフォーマンスの電源ボタンであると信じて騙してはいけません。ワークロードによっては、インデックス付きビューを維持すると、それに対するクエリから得るよりもパフォーマンスが高くなる可能性があります。

いくつかの選択肢があります:

(1)dbo.TbDocActions(DocID, ID DESC)に非クラスター化インデックスを作成するか、既存のクラスター化インデックスを削除してDocID, ID DESCに変更します。 (IDがID列である場合は、おそらくそれも主キーとして設定されており、デフォルトでクラスター化されますが、そうである必要はありません。)

(2)DocIDを主キーとして別のテーブルを維持し、トリガー(またはストアドプロシージャのみへの書き込みを制限している場合はストアドプロシージャ)を使用して、最高のIDを最新に保つ。 3つのDMLタイプすべて(insertupdateおよびdelete)のロジックが必要になります。理論上、これらのいずれもMAXに影響を与える可能性があるためです。計算。 (明らかに、両方のID列がIDENTITYである場合、リスクは低くなります。)列をメインテーブルに追加して、同じ方法で最新の状態に保つこともできます。

同じ警告が適用されることに注意してください。他のテーブルでインデックスを追加したり値を維持したりすると、この特定のクエリにメリットがありますが、魔法ではありません-ワークロードの他の部分に影響を与える可能性があります。単一のクエリを「修正」することを考えるときは、常にビジネスサイクル全体を考慮する必要があります...

5
Aaron Bertrand