web-dev-qa-db-ja.com

「アーカイブされているが利用可能な」データ用のSQL Serverデータベース設計

「縮小」しようとしているこの大規模なデータベース(> 1TB)があります。データベースは1つの主要なエンティティを中心に展開します。「訪問」と呼びましょう。議論のために、それは医療行為のためのデータベースであるとしましょう。

手順、年次、フォローアップ、予防接種など、合計30の訪問「タイプ」があり、それぞれが「訪問」のサブテーブルです。 「visit_immuno」。

データベースは2000年以降約12年分のデータを蓄積しています。約3年分のデータを「ライブ」バージョンで保持し、残りを「old_data」データベースでライブにすることを誰かが提案しました。日付は正規化されているため、「訪問」テーブルにのみ格納されます。 Visitテーブルには、ROWVERSION列とBIGINT疑似ID(クラスター化)列も含まれています。すべての意図と目的で、クラスタリングキーにSEQUENCE(SQL Server 2012 Enterprise)が入力されているとしましょう。cidという名前を付けます。

_visit.date_は常にクラスタリングキーと同じ順序であるとは限りません。たとえば、医師が長期の通院を続け、データの「ブリーフケース」を返した場合、メインテーブルにマージされます。 「visit」テーブルにいくつかの更新があり、ROWVERSION列がcidおよびdate列の両方と同期しなくなります-簡単に言えば、このため、ROWVERSIONcidも適切なパーティションキーを作成しません。

「ライブ」からデータを削除するためのビジネスルールは、_visit.date_が36か月以上である必要がありますand子_visit_payment_レコードが存在する必要があります。また、「old_data」データベースには、_visit%_以外の基本テーブルは含まれていません。

したがって、次のようになります。

ライブDB(毎日使用)-すべてのテーブルOld-Data DB-_visit%_テーブルの古いデータ

この提案では、_Live DB_(_visit%_を除く)のすべてのベーステーブルにSynonymsを含むシェルであるCombined DBが必要です- Views 2つのデータベースの_visit%_テーブル全体のUNION ALL。

同じインデックスが_Old-Data_ DBで作成されると仮定すると、クエリはUNION-ALL Viewsで適切に実行されますか? UNION-ALL Viewsの実行プランに影響を与える可能性のあるクエリパターンの種類は何ですか?

12
孔夫子

便宜上、ライブデータベースはLiveDbと呼ばれ、アーカイブデータベースはArchiveDbと呼ばれると想定します

  • シノニムを介してLiveDbデータベースのテーブルを指すArchiveDbにUNION ALLビューを追加します(シノニムと組み合わせたdbを実行する必要はありません)
  • visit.dateの「パーティション」と、この列がvisit_paymentsにない場合は、これも非正規化します(これにより、同じ場所にある結合のパフォーマンスが向上します)。
  • 可能であれば、2つの大きなテーブルのみをアーカイブします(オプティマイザが作動する可能性を減らします)。 UNION ALLビューと他のテーブルをLiveDbに保持して、小さいテーブルへのすべての結合がローカルに保持されるようにします
  • テーブルに含まれるvisit.dateの範囲を記述するLiveDbArchiveDbの両方のテーブルにCHECK制約を追加します。これは、オプティマイザが列visit.dataを含むシークとスキャンの両方からアーカイブテーブルを削除するのに役立ちます。この制約は定期的に更新する必要があります。
  • UNION ALLビューで、visit.dataでフィルタリングするWHERE基準を追加します。これは、チェック制約ですでに指定したヒントに追加されます。これにより、フィルターが押し下げられる可能性が最大になります
  • EEを使用している場合は、アーカイブデータベースのテーブルをパーティション分割します(ただし、ライブデータベースにはありません)。本当に豪華にしたい場合は、アーカイブデータベースのファイルグループレベルのバックアップ/復元を使用して、バックアップ時間を節約します。
  • AchiveDbがSIMPLEリカバリーモードになっていない場合は、それを設定することを検討してください。 ArchiveDbのトランザクションログバックアップが必要になることはほとんどありません。
  • LiveDbArchiveDbの間でデータを移動するときに、INSERT ... WITH(TABLOCK)SELECT ... WITH(ROWLOCK)を使用して、宛先でのロギングを最小限に抑えます

上記のすべては、オプティマイザがシークとスキャンからアーカイブテーブルを削除することを保証するものではありませんが、可能性が高くなります。

相殺が起こらないとき。これらはあなたが見るかもしれない効果です(このリストは不完全かもしれません)。シークの場合、すべてのクエリで追加のシークを取得します(これによりIOPSが増加します)。スキャンの場合、アーカイブテーブルとライブテーブルの両方をスキャンしてしまう可能性があるため、パフォーマンスに悪影響を与える可能性があります。オプティマイザーを作動させる一般的な方法は次のとおりです。

  • visit%テーブルを結合して、結合基準にvisit.dataを含めない場合(これが非正規化する理由です)。このため、クエリの一部を変更することができます
  • visit.dataと別のテーブル(日付のディメンションなど)とのハッシュ結合を取得すると、テーブルが適切に削除されない場合があります
  • アーカイブされたテーブルでデータを集計しようとした場合
  • 何かにフィルタをかける場合、visit.data、たとえばビューのキーを直接検索します。

最後のシナリオでは、cidに別のチェック制約を追加することで、最悪の影響から身を守ることができます(可能な場合)。テーブルの行の日付と進行に関して、cidのシーケンスが「クリーン」ではないことを説明しました。しかし、「このvisit.dataなので、この数値を超えるcidはありません」などの情報を含むテーブルを維持できますか?これにより、追加の制約が発生する可能性があります。

もう1つ注意すべき点は、パーティションビューにクエリを実行すると、並列クエリがより多くのスレッドを生成する可能性があることです(両方の「サブテーブル」が同じ並列最適化に公開されるため)。そのため、サーバーでのMAXDOPまたは並列クエリを制限することができます。

ちなみに、クエリをよく知っている場合は、2つのデータベースに同じインデックスが必要ない場合もあります(これにより、100%確実にテーブルを削除できると想定しています)。 ArchiveDbの列ストアの使用を検討することもできます。

4
Thomas Kejser