インデックス付きビューを使用して、最もよく使用されるいくつかのビューのパフォーマンスを向上させることを検討してきました。
ただし、インデックス付きビューは、一意ではないクラスター化インデックスをサポートしていません。これは、データベース構造の残りの部分によって設定された優先順位に少し影響します。
たとえば、ここにいくつかのテーブルを簡略化したバージョンがあります。
-Groups-
Group ID GroupName
-Users-
UserKey UserName FullName GroupID
インデックスは、Groups.GroupID(非クラスター化)およびUsers.GroupID(クラスター化)にあります。クラスター化されたキーは、最も一般的には特定のグループからの一連のユーザーが取得されるため、UsersテーブルのGroupIDにあります。明らかに、グループごとに複数のユーザーがいるため、このクラスター化インデックスは一意ではありません。
このため、この例のようにビューにインデックスを付けるときに、この優先順位に従う方法が少し不確かになります。これは、一意でないクラスター化インデックスを持つことができないためです。
ConsumableID ConsumableVariantID AllowThresholdOverwrite FullPath GroupID ManufacturerID Type ModelID
101 29 1 0.1.2.4. 4 3 3 2
実際には、常に一意であるこのビューの唯一の値はConsumableID列です。そのため、インデックスを配置する場所についてほとんど選択肢がありません。
通常のテーブルで許可されているのに、ビューが一意でないクラスター化インデックスを許可しないのはなぜですか?
次の説明は this Microsoft Technical Article に記載されています。
なぜビューの最初のインデックスをクラスタ化して一意にする必要があるのですか?
インデックス付きビューのメンテナンス中にキー値によってビュー内のレコードを簡単に検索できるようにし、重複したビューの作成を防ぐために一意である必要があります。クラスター化されたインデックスのみが一意性を強制し、同時に行を格納できるため、クラスター化する必要があります。
SQL Serverは、デルタ代数のシステムを使用して、インデックス付きビューをベースデータと一致させます。また、1つ以上のインデックス付きビューに影響を与える各DMLクエリのビューメンテナンスクエリプラン演算子を自動的に組み込みます。ビューに一意のクラスター化インデックスを設定すると、実装の詳細が大幅に簡素化されます。
現在の配置では、固定形状のメンテナンスオペレーターツリーの形状をベースDMLクエリツリーに組み込むことができ、直交性を提供してテストも簡略化します。最終的に、インデックス付きビューは、非一意のクラスター化インデックスをサポートするように1日拡張される可能性がありますが、無制限の時間と無限のリソース(どちらも執筆時点ではSQL Server開発チームには当てはまりません)があれば、すべてが可能になります。
複雑な更新クエリプランの構築がどのように行われるか、および微妙なバグが侵入しやすいかを示す例については、 このバグの例 がMERGE
およびフィルターされたインデックス(機能インデックス付きビューと密接な関係があります)。
SQL Serverでは、すべてのインデックスキーは内部的に一意である必要があります。これは、1つの行だけをアドレス指定するロックキーを取得するために必要です。インデックスのメンテナンスにも必要です。値が1つしかない列(100%重複)のNCIを想像してください。行がテーブルから削除された場合、ストレージエンジンは対応するNCI行を見つけて削除する必要があります。すべてのNCI行が区別できない場合、これは不可能です。
したがって、ビューのCIは、エンジンが機能するために(内部で)一意である必要があることがわかります。
インデックスを一意にしない場合でも、SQL Serverは内部的に一意にします。ヒープテーブルのNCIの場合は、行ブックマークを追加します。一意でないCIの場合は、一意識別子列を追加します。 CIを含むテーブルのNCIの場合、自分でまだ指定していないCIキー列を追加します(これには、一意化記号が含まれる場合があります)。
インデックス付きビューの場合に追加できる明確な列はありません。したがって、SQL Serverはこれを自動的に実行できません。
通常、ビューにCIで使用する一意の列のセットを持たせるためにどの列を追加できるかは、人間には明らかです。これらは通常、基になるテーブルの1つのPK列またはCI列です。ビューにGROUP BY
通常、グループ化キーにインデックスを付けます。