私のテーブル構造は以下の通りです:
_ 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()
集約関数を使用できません。
すでにご存じのとおり、インデックス付きビューではMAX()
集計を使用できません。いずれにせよ、インデックス付きビューの作成は不思議なパフォーマンスの電源ボタンであると信じて騙してはいけません。ワークロードによっては、インデックス付きビューを維持すると、それに対するクエリから得るよりもパフォーマンスが高くなる可能性があります。
いくつかの選択肢があります:
(1)dbo.TbDocActions(DocID, ID DESC)
に非クラスター化インデックスを作成するか、既存のクラスター化インデックスを削除してDocID, ID DESC
に変更します。 (ID
がID列である場合は、おそらくそれも主キーとして設定されており、デフォルトでクラスター化されますが、そうである必要はありません。)
(2)DocID
を主キーとして別のテーブルを維持し、トリガー(またはストアドプロシージャのみへの書き込みを制限している場合はストアドプロシージャ)を使用して、最高のID
を最新に保つ。 3つのDMLタイプすべて(insert
、update
およびdelete
)のロジックが必要になります。理論上、これらのいずれもMAX
に影響を与える可能性があるためです。計算。 (明らかに、両方のID
列がIDENTITY
である場合、リスクは低くなります。)列をメインテーブルに追加して、同じ方法で最新の状態に保つこともできます。
同じ警告が適用されることに注意してください。他のテーブルでインデックスを追加したり値を維持したりすると、この特定のクエリにメリットがありますが、魔法ではありません-ワークロードの他の部分に影響を与える可能性があります。単一のクエリを「修正」することを考えるときは、常にビジネスサイクル全体を考慮する必要があります...