web-dev-qa-db-ja.com

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

私はずっと前にどこかで読んだことがあります。この本は、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は、今年登録した学生に基づいています。また、学生向けのビューは、ストアドプロシージャなどの他の場所を使用することもできます。

43

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

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

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

    例えばこのビュー列はどのテーブル列を参照しますか? Lemme Dig through 4レベルのビュー定義...

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

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

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

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

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

それらが必要になることはめったにないことがわかりました。


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

  • 保持:ネストされたビューを保持することにより、上記で列挙した長所と短所が発生します。

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

    1. ビューのすべてのオカレンスをベースクエリに置き換える必要があります。

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

47
Nick Chammas

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

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

26
Aaron Bertrand

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

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

クエリとビューを同時に作成している場合、ビューを使用するとデバッグが煩雑になることに同意します。しかし、tryed-n-trustedビューを使用している場合は、デバッグが簡単になります。ビューは既に呼び出し音を通過しているため、問題が発生していない可能性が高いことがわかります。

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

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

編集:

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

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

7
blah blah

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

4
Ray

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

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

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

0
Narwhal