ビューにWHERE句を追加すると、ビューが最適化されますか?


28

ビューの内側または外側でビューをフィルタリングすると、違いが生じますか?

たとえば、これら2つのクエリに違いはありますか?

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

または

SELECT Id
FROM MyView
WHERE SomeColumn = 1

MyView定義されます

SELECT Id, SomeColumn
FROM MyTable

ソーステーブルがリンクサーバー上にある場合、答えは異なりますか?

リンクサーバーから大きなテーブル(44mil行)を2回クエリし、結果の集計を取得する必要があるため、私は尋ねています。データにアクセスするために2つのビューを作成する必要があるかどうか(クエリごとに1つ)、または単一のビューと1つのWHERE句で処理できるかどうかを知りたいです。


1
テーブルが1つしかない場合に、なぜビューを使用するのでしょうか。
-HLGEM

3
@HLGEMセキュリティ?
JNK

2
@HLGEMビューには、実際には異なるサーバー上の複数のデータベースへの複数のクエリが含まれており、それらをすべてで結合しますUNION ALL。データが必要なときにUNIONクエリを書き換えるよりも、Viewを使用する方がはるかに簡単です。
レイチェル


1
@datagod心に留めておきます、ありがとう:)この場合、多数のサーバーからデータを収集し、いくつかの計算を実行し、多数のレポートを出力するかなり小さなアプリがあります。計算の中にはかなりリソースを消費するものがあるため、独自のデータベースがあります。他のすべてから計算したいと思いました。
レイチェル

回答:


12

これらの2つの選択肢の間で、計画やパフォーマンスにまったく違いは見られないはずです。ビューがクエリされると、ベーステーブルに対するクエリに展開されます。つまり、同じシークまたはスキャンが使用されます。

現在、データ型との選択性によってはMyColumn、ベーステーブルにフィルターインデックスを作成する場合(SQL Server 2008+に移行する場合)、パフォーマンスが向上する可能性がありますが、これはビューを介しても変わりませんまたはなし。


3
何についてのこの質問を持つクエリなぜ求めている、whereビュー外節はそれがビューに入れていたときよりも、そんなに長い時間がかかりますか?
レイチェル

1
ビューがパフォーマンスのためではない場合、それらは構造のためだけですか?
profimedica 14

1
@profimedicaのインデックス付きビューは、パフォーマンス上の理由で作成できます(たとえば、実行時に計算するのではなく、集計などの中間結果を保存するため)。ビューが具体化されない場合、さまざまな理由が考えられます。DRY(多くの異なるクエリで実行される一般的な結合またはフィルター)、セキュリティ、難読化、スキーマの単純化。
アーロンバートランド

5

違いがないことを示す簡単な例を示します。データベースはAdventureWorksデータベースです。

2つのビュー定義:

create view Person.vContactWhere
as

    select *
    from person.Contact
    where ContactID = 24

go

create view Person.vContactNoWhere
as

    select *
    from person.Contact

go

WHEREビュー定義に句が含まれる最初のクエリは次のとおりです。

select *
from person.vContactWhere

実行計画は次のとおりです。

ここに画像の説明を入力してください

そして、WHEREビュー定義ではなく、SELECTクエリ内の句を持つ2番目のクエリ:

select *
from person.vContactNoWhere
where ContactID = 24

その実行計画は次のとおりです。

ここに画像の説明を入力してください

これらの実行計画からわかるように、それらは同一の結果で同一です。このタイプのロジック/デザインが異なる結果を出力する状況は知りません。だから、私はあなたがどちらにしても安全だと言って喜んで、個人的な好み(または店の手順)で行きます。


1
何についてのこの質問を持つクエリなぜ求めている、whereビュー外節はそれがビューに入れていたときよりも、そんなに長い時間がかかりますか?
レイチェル

1
@Rachel gbnは彼の投稿と彼が指摘した記事でそれをかなりよく説明したと思う。私はそれを他にどのように置けばいいのか分かりません。
トーマスストリンガー

私はそれをリンクしました。なぜなら、その場合、実行計画は同じではなく、あなたの答えが言っているものとは異なるからです。
レイチェル

1
@Rachelこの例の問題は、変換規則が欠落していることです。ビューだけでなく、CTEやその他のテーブル式にも適用されます。一般的な場合、結果を変更するため、ランク付け関数を含むテーブル式に述語をプッシュダウンすることは無効です。この場合に有効である理由は、Where句がに適合するためPARTITION BYです。SQL Server 2008には、SelOnSeqPrjこの特定のケースを認識する新しいルールがあるようです。
マーティンスミス


2

私が読んいるもの 基づいて、SQLは実行計画を決定するときにサブクエリのような標準ビューを使用します。

クエリの例を使用して、

SELECT Id
FROM MyView
WHERE SomeColumn = 1

どこMyViewで定義されています

SELECT Id, SomeColumn
FROM MyTable

以下と同じ実行計画を生成する必要があります

SELECT Id
FROM 
(
    SELECT Id, SomeColumn
    FROM MyTable
) as T
WHERE SomeColumn = 1

しかし、この実行計画は、生成されるものとは異なる場合があります

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

この答えがインデックス付きビューでも同じかどうかわかりません


私はそれがそのような明示的なテキスト置換だとは思わない。
アーロンバートランド

@AaronBertrandあなたは正しいかもしれません。私は正直なところ何も知りません...私は行くにつれて学んでいます:)その仮定は、ビューがマクロのようなものであるということについて私が読んでいた他のものに基づいていました。質問を少し編集して、インデックス付きビューではなく標準ビューを参照するように指定しました。
レイチェル

@Rachel-代用されたツリーがテキストレベルではなく置換されます。
マーティンスミス

@MartinSmith Hrrmmは私が言ったことではありませんか?テキストが同じになるのではなく、実行計画が同じであるべきだと?「代数木」を理解しているかどうかわからない
レイチェル

これは、「ビューのテキストをクエリに挿入する」というQ自体へのコメントと、上記のアーロンのコメントへの応答でした。解析/コンパイル段階に関する情報はこちら。実際、あなたの答えはテキスト置換についても言及しています。これが価値のある区別であるかどうか。わからない!しかし、なぜsp_refreshviewテキスト置換の概念では必要ないのに必要なのかは説明されていると思います。
マーティンスミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.