web-dev-qa-db-ja.com

インデックス付きビューを作成できるように、ビューの左結合を置き換えるにはどうすればよいですか?

データベース内のテーブルを正規化し、それを非正規化するために、2つのテーブルからビューを作成しました。ビューにクラスター化インデックスを作成しようとすると、ビューは左外部結合で作成されたため、作成できませんでした。この以前の投稿で提案された方法と同じように、結果のビューにnull値を表示したいので、左結合を使用しました。

1つの列の片側がnullである結合に関する質問

テーブルの構造と関係は、上記のリンクで説明したものと非常によく似ています。

左結合を内部結合に変換できなかったため、ここで壁にぶつかったように見えました。これは、結合された列のいずれかでnull値を持つすべてのレコードを除外するためです。私の質問は次のとおりです。

  1. 外部結合または自己結合でインデックス作成が許可されないのはなぜですか?
  2. この種のインデックス付けされていないビューでパフォーマンスに影響はありますか?
  3. 誰かがこの問題の回避策を知っていますか?

昨日SQLServerコースを終了したばかりなので、続行する方法がわかりません。コメントをいただければ幸いです。乾杯。

19

「回避策」があります ここ 結合でNULLをチェックし、テーブルにNULL表現値を持つことを含みます

NULL値

INSERT INTO Father (Father_id, Father_name) values(-255,'No father')

参加

JOIN [dbo].[son] s on isnull(s.father_id, -255) = f.father_id
7
Magnus

これが代替案です。 Bを含まないAのマテリアライズドビューが必要です。これは直接利用できません...代わりに、2つのビューをマテリアライズします。すべてのAの1つと、Bを持つAのみの1つ。次に、B以外のAを取得して、Bを持たないAのみを取得します。これは効率的に実行できます。

2つのマテリアライズドビュー(mAとmAB)を作成します(編集:mAはベーステーブルになります)。 mAには、AとBの間の結合がありません(したがって、すべてのAの期間が含まれます[したがって、Bに一致するものがないレコードが含まれます])。 mABはAとBの間で結合します(したがって、AとBのみが含まれます[したがって、Bで一致しないレコードは除外されます])。

Bで一致しないすべてのAを取得するには、一致するものをマスクします。

with ids as (
  select matchId from mA with (index (pk_matchid), noexpand)
  except
  select matchId from mAB with (index (pk_matchid), noexpand)
)
select * from mA a join ids b on a.matchId = b.matchId;

これにより、IDを取得するためのクラスター化インデックスと、探しているmAからデータを取得しようとするクラスター化インデックスの両方に対して左アンチセミ結合が生成されます。

基本的に、SQLは、ISNではないデータよりもIS)のデータを処理するのにはるかに優れているという基本的なルールがあります。2つのソースを具体化することで、いくつかの魅力的なセットベースのオプションが得られます。 。これらのビューのコストとそれらの利益を自分で比較検討する必要があります。

13
cocogorilla

良い回避策はないと思います。これについてできることは、ビューから実際のテーブルを作成し、それにインデックスを設定することです。これは、データが更新されるときに定期的に呼び出されるストアドプロシージャによって実行できます。

Select * 
into <REAL_TABLE>
From <VIEW>

create CLUSTERED index <INDEX_THE_FIELD> on <REAL_TABLE>(<THE_FIELD>)

ただし、これは、データが数秒ごとに更新されない場合にのみ注目に値するアプローチです。

6
Klaus

論理的には、2つの別々のクエリを実行しています。 「ALEFTJOIN B」は、「(A JOIN B)UNIONA」の省略形です。

最初のクエリは、テーブルBに結合されたテーブルAの内部です。これは、すべての手間のかかる作業が行われる場所であるため、インデックス付きのビューを取得します。

2番目のクエリは、結合列のいずれかがnullであるテーブルAだけです。最初のクエリと同じ出力列を生成し、それらにnullを埋め込むビューを作成します。

それらを返す前に、2つの結果を結合するだけです。回避策は必要ありません。

1
Anon

私は1の答えに取り組みますが、今のところ:

[2]。ビューは、udnerlyingテーブルの同等のクエリよりもパフォーマンスが高くも低くもなりません。カバーするインデックス、できれば結合された列のインデックスなどについては、通常のアドバイスがすべて適用されます。

[3]。実際の回避策はありません。インデックス付きビューに対する制限のほとんどは、それらを掘り下げてみると、非常に正当な理由で存在します。

通常、ビューを作成するだけで、特定のパフォーマンスの問題がない限り、それ以上は行いません。

自分の頭の中で再構築したら、1の答えを追加しようとします。