ネストされたビューは優れたデータベース設計ですか?


42

私はずっと前にどこかで読んだことがあります。この本は、SQL Serverでネストされたビューを持つことを許可すべきではないと述べています。私たちがそれができない理由がわからないか、間違った記述を覚えているかもしれません。

学生

SELECT studentID, first_name, last_name, SchoolID, ... FROM students

CREATE VIEW vw_eligible_student
AS 
SELECT * FROM students
WHERE enroll_this_year = 1

先生方

SELECT TeacherID, first_name, last_name, SchoolID, ... FROM teachers

CREATE VIEW vw_eligible_teacher
AS 
SELECT * FROM teachers
WHERE HasCert = 1 AND enroll_this_year = 1

学校

CREATE VIEW vw_eligible_school
AS 
SELECT TOP 100 PERCENT SchoolID, school_name 

FROM schools sh 
JOIN
     vw_eligible_student s 
     ON s.SchoolID = sh.SchoolID
JOIN 
     vw_eligible_teacher t
     ON s.SchoolID = t.SchoolID

私の職場では、社内データベースアプリケーションの1つを調査しました。ビュースタックの2つまたは3つのレイヤーが相互に存在することがわかったオブジェクトを確認しました。過去に読んだことを思い出させてくれました。誰もそれを説明するのを助けることができますか?

そうでない場合は、SQL Serverのみに限定されているか、一般的なデータベース設計用であることを知りたいと思います。

追加情報:会社の例を更新しました。あまり技術的でない(この例では列が多すぎる)ことなく、少し一般的なものに変更します。ほとんどの場合、ネストビューは抽象ビューまたは集約ビューに基づいています。たとえば、数百の列を持つ大きな学生テーブルがあります。言う、Eligible Student View今年入学する学生に基づいています。また、学生の対象となるビューは、ストアドプロシージャなどの他の場所を使用することもできます。


3
特定のプラットフォームに関係なく、同じ長所と短所がおおよそ同じになることを提出します。
アーロンバートランド

回答:


47

プラットフォームに関係なく、次の注意事項が適用されます。

(-)ネストされたビュー:

  • 理解とデバッグが難しい

    例:このビュー列はどのテーブル列を参照していますか?Lemmeは 4レベルのビュー定義を掘り下げます...

  • クエリオプティマイザーが最も効率的なクエリプランを作成するのを難しくする

    参照してください。このこのこの、およびこの事例証拠のために。これと比較すると、オプティマイザーは多くの場合、ネストされたビューを正しくアンパックし、最適なプランを選択するのに十分なほどスマートですが、コンパイルコストがかかります。

    ビュークエリをベーステーブルに対して記述された同等のクエリと比較することにより、パフォーマンスコストを測定できます。

(+)一方、ネストされたビューでは次のことができます。

  • 集約またはビジネスルールを一元化および再利用する
  • 基礎となる構造を抽象化します(たとえば、他のデータベース開発者から)

それらが必要になることはめったにありません。


この例では、ネストされたビューを使用して、特定のビジネス定義を集中化および再利用しています(「対象となる学生とは」など)。これは、ネストされたビューの有効な使用方法です。このデータベースを保守または調整する場合は、それらを保持するコストと削除するコストを比較検討してください。

  • 維持:ネストされたビューを維持することにより、上記の利点と欠点が生じます。

  • 削除:ネストされたビューを削除するには:

    1. ビューのすべての出現を基本クエリに置き換える必要があります。

    2. 対象となる生徒/教師/学校の定義が変更された場合、関連するビュー定義を更新するのではなく、関連するすべてのクエリを更新することを忘れないでください。


1
+1、クエリオプティマイザーの「ハード」を「ほぼ不可能」に置き換えます。:)
ジェイソン

1
@ジェイソン-私は同意し、いくつかの具体的な例にリンクできるといいのですが。これがそうである理由を説明または実証する参考文献を知っていますか?
ニックチャマス

1
私が見つけることができるのは、ネストされたビューが使用されると、「フラット化された」SQLと比較してパフォーマンスの問題が発生するという事例証拠です。sqlservercentral.com/blogs/2cents/archive/2010/04/05/… この問題は、DB(この場合はSQL Server)がテーブルを結合する前に特定のフィルターを適用しないという事実に起因するようです。クエリに必要以上に時間がかかるようにします。
ジェイソン

7
クエリオプティマイザーの問題には同意しません。すべてのビューを解決した後の結果のクエリは、ビューの変換が何回行われても同じになるためです(オプティマイザーが問題なく削除できる中間結果セットのいくつかの余分な列を除く)。これにより、デバッグが終了します。IMOを使用すると、中間結果を見て問題がどこで発生したかを確認できるため、ネストされたビューを持つことがデバッグしやすくなります。
サイモンリヒター

1
組み込みデータベースサーバーを作成しましたが、ビューを最初に解決してから、結果のクエリを最適化することは明らかなルートでした。実際、ビューのすべてのクエリがすべての列を返すことはほとんどありません。クエリの途中でビューデータを実現すると何かが得られる理由を考えることさえできないので、それは私にとって簡単なことではありませんでした。
サイモンリヒター

26

ネストされたビューは、集約の繰り返しを防ぐために使用される場合があります。メッセージをカウントし、ユーザーIDでグループ化するビューがあるとします。100を超えるメッセージを持っているユーザーの数をカウントするビューなどがあります。これは、ベースビューがインデックス付きビューである場合に最も効果的です。パフォーマンスがおそらく2倍のインデックスメンテナンスにかかるため、必ずしも別のインデックス付きビューを作成して、少し異なるグループ化でデータを表す必要はありません。元のビューに対して十分です。

これらがすべてselect *を実行するだけでネストされたビューであるが、順序またはトップを変更している場合、これは、多数のネストされたビューよりも、パラメーター(またはインラインテーブル値関数)を使用するストアドプロシージャとしてカプセル化する方が良いようです。私見では。


4
「これは、ベースビューがインデックス付きビューである場合に最も効果的です。」重要なポイント。
ニックチャマス

7

SQLの新しいバージョン(2005以降)は、ビューの使用を最適化するのに適しているようです。ビューは、ビジネスルールを統合するのに最適です。EG:私が働いている場所には、通信製品データベースがあります。各製品はレートプランに割り当てられ、そのレートプランはスワップアウトでき、レートプランのレートは、レートが増加または変更されるとアクティブ化/非アクティブ化されます。

簡単にするために、ネストされたビューを作成できます。1番目のビューは、必要なテーブルを使用してレートプランをレートに結合し、次のレベルのビューに必要なデータを返します。2番目のビューでは、アクティブなレートプランとそのアクティブなレートのみを分離できます。または、単に顧客レート。または従業員料金(従業員割引の場合)。または、ビジネス対住宅の顧客料金。(レートプランは複雑になる可能性があります)。重要なのは、基本ビューにより、料金プランと料金のビジネスロジック全体が1つの場所で適切に結合されることです。ビューの次のレイヤーでは、特定のレートプラン(タイプ、アクティブ/非アクティブなど)にさらに焦点を当てます。

クエリとビューを同時に作成している場合、ビューによってデバッグが煩雑になる可能性があることに同意します。ただし、信頼できるビューを使用している場合は、デバッグが容易になります。あなたはそのビューが既にリンガーを介していることを知っているので、問題を引き起こしていない可能性が高いことを知っています。

しかし、問題はあなたの意見を思い付くことができます。「製品が非アクティブな料金プランにのみ関連付けられている場合はどうなりますか?」または「レートプランに非アクティブなレートのみが含まれている場合はどうなりますか?」それは、ユーザーエラーをキャッチするロジックを使用して、フロントエンドレベルでキャッチできます。「エラー、製品は非アクティブな料金プランです...修正してください」。また、請求の実行前にクエリ監査を実行して再確認することもできます。(すべてのプランを選択し、アクティブなレートプランビューに参加し、対処する必要がある問題としてアクティブなレートプランを取得しないプランのみを返します)。

これの良い点は、レポート、請求などのクエリを大幅に集約できるビューです。顧客アカウントビューを作成し、アクティブな顧客のみの第2レベルのビューを作成できます。顧客の住所を考慮したチーム。製品のビュー(顧客が持っている製品に参加)を持つチーム。製品のレートプランを表示するチーム。製品の機能を考慮してチーム化します。表示、表示、表示、整合性を確保するための各試行錯誤。ビューを使用した終了クエリは非常にコンパクトです。

編集:

ビューが単なるテーブルのフラットクエリよりも優れている方法の例として、いくつかの変更を行うために臨時の請負業者を招きました。彼らは物事に対する見解があると彼に言ったが、彼は彼のすべての質問を平らにすることに決めた。課金は、彼のクエリのいくつかから物事を実行していました。彼らは物事の複数の料金プランと料金を取得し続けました。彼のクエリは、料金プランがその/その料金を使用することになっていた開始日と終了日の間にある場合にのみ料金の請求を許可する基準が欠落していることがわかりました。おっと。彼がビューを使用していた場合、すでにそのロジックを考慮していたでしょう。

基本的に、パフォーマンスと健全性を比較検討する必要があります。データベースのパフォーマンスを向上させるために、あらゆる種類の凝った作業を行うことができます。しかし、それが新しい人が引き継ぐ/維持するのが悪夢だということを意味する場合、それは本当に価値がありますか?新しい男が論理を変更するために必要なすべてのクエリを見つける必要があります(そして、彼がそれらを忘れる/太るのを危険にさらす)b / c誰かがビューが「悪い」と決めたコアビジネスロジックを、他の数百のクエリで使用できるものに統合しなかったのですか?本当にあなたのビジネスとIT / IS / DBチーム次第です。しかし、パフォーマンスよりも明快さと単一ソースの統合を好むでしょう。


4

本当の問題は、それ自体にネストされたビューではありません。実際の問題は、開発者が既存のビューに追加の調整を重ねるにつれて、ネストされたビューが急増することです。定義内のビューの1つに実際に結合された4つのレイヤーのネストされたビューを持つクエリを見つけました。問題を分析して解決するよりも簡単な方法を採用する傾向が、問題の根本です。


0

私の環境では、実稼働サーバーからレポートサーバーに多くのテーブルを複製します。レポートサーバーには、レプリケートされた運用テーブルに基づいており、ネストされたビューが多数あります。レプリケーションを開始する前に、レプリケーションを可能にするためにすべてのビューを削除する必要があります(本番環境ではテーブル構造が頻繁に変更されるため、ドロップアンド作成を使用します)。レプリケーションが終了したら、すべてのビューを再構築する必要があります。

ここからが面白い部分です。ビューの多くはネストされているため、特定の順序で再構築する必要があります。ビューの定義に変更を加えている間は、正しい再構築順序を維持するように注意する必要があります。それは完全に混乱です。レプリケーションを使用する場合、またはビューのソースであるテーブルを単にドロップして再構築する場合は、ネストされたビューを使用しないことを強くお勧めします。

パフォーマンスは別のものです。他のビューに基づくビューは、実行する複数のクエリに他なりません。大きなクエリをまとめてジョブを作成し、テーブルを作成する方が簡単です。より簡単になり、パフォーマンスが向上します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.