web-dev-qa-db-ja.com

ビューのパフォーマンスを改善するための提案が必要

SQL Server 2008のビューのパフォーマンスを向上させたいと考えています。このビューは、あまり技術者ではない人々がこれらの属性をすべて非正規化するために広く使用しているレポートデータベースに存在します。

これは、非常に複雑で、長期にわたる見解です。私たちは1900万人以上の人々がいて、各列に入る多くのロジックがあります。たとえば、人が亡くなっているかどうかに関するインジケータがあり、それは3つのCTE(共通テーブル式)とケースステートメントに依存しています。

基本的に、それは悪夢です。

パフォーマンスを改善する方法を見つける必要があります。これをテーブルに変更することはできません。データは秒単位で正確でなければなりません。インデックス付きビューに変更するのは簡単です。複数のデータベースのデータを使用します。列の構造を変更することはできません。既存のレポートの多くが壊れてしまうからです。

ツールボックスに役立つと思われるツールはありますか?ストアドプロシージャまたは関数が役立つかどうか疑問に思っています。たぶん計算された列を持つテーブルでしょうか?個人の識別情報を毎晩取得してテーブルに格納することはできますが、ほとんどの列はライブデータに依存しています。

6
JHFB

ビューは通常、パフォーマンスのために実装されていません。現在、明示的なインデックス付きビュー(SQL Serverが管理するビューにすぎません)を実装することはできませんが、ファクトを手動で手動で管理することはできます。

たとえば、3人のCTEと1つのCASE式を使用して、「誰かが死んでいるかどうか」を現在計算していると述べた(申し訳ありませんが、説明が難しいため、これはステートメントではありません)。

ビューにアクセスするたびにこのCTEのセットを参照する代わりに、そのファクトをテーブルに入れて(潜在的にユーザーごとに計算する必要がある他のファクトと一緒に)、バックグラウンドで定期的に計算してみませんか?したがって、おそらく5分ごと(つまり、Swagであり、何が適切かを判断する必要があります)、SQL Serverエージェントジョブを実行して、現在真実であるとわかっていることに基づいてテーブルを再作成します。これで、ビューは、ユーザーが待機している間、何度も何度も計算するのではなく、そのスクリプトの出力であるテーブルを参照する必要があります。だから例えば:

CREATE TABLE dbo.PersonProperties
(
  PersonID INT PRIMARY KEY REFERENCES dbo.Persons(PersonID),
  IsDead BIT NOT NULL DEFAULT 0
);

これで、ジョブはそのテーブルをCTEの結果と単純にマージでき、ビューにはそのテーブルへの参照を含めることができ、PKの結合とともにBIT列を単にプルします。これにより、クエリ時に、そのロジックすべてを毎回再評価するよりもはるかに安価になるはずです。

ブロックを最小限に抑えるには(たとえば、ユーザーがジョブの実行中に同時にビューにアクセスしているとき)、 "schema switch-a-roo"と呼んでいるものを実装できます。

http://www.sqlperformance.com/2012/08/t-sql-queries/t-sql-tuesday-schema-switch-a-roo

したがって、操作全体で負荷の高いクエリのリソースをロックする代わりに、発生する唯一のブロッキングは、メタデータの切り替えが実際に行われるときです。


これは、データが正確でない短い期間を許容できる限り機能します。そのウィンドウをかなり狭くすることができますが、その間に人が死ぬ可能性が常にあり、一時的にクエリが返され、まだ生きていることが返されます。これを受け入れる余裕がない場合は、その事実をデータベースに最初に導入するプロセスの一部にして、CTEがそれをすぐに反映することを確認しますand新しいテーブルにもすぐに反映されます。

まだ十分ではありませんか?ユーザーに「ダーティ」フラグを付け、2番目の変更が入ると、ビューは「クリーン」なユーザーの古いデータと結合または左結合し、「ダーティー」なユーザーのライブデータのみを追跡できます。

6
Aaron Bertrand