web-dev-qa-db-ja.com

大きなテーブルを分割してパフォーマンスを向上させる

これは 以前の質問 のフォローアップです。 SQL Server 2008 R2 Standardサーバーがあり、単一のデータベースを保持していますが、それ自体は大きなテーブル以外はほとんどありません。

テーブルは1億行以上(35列)で、1日あたり約250,000行で増加しています。すべてのデータが「オンライン」である必要があり、ほとんどの列は何らかの方法で検索可能である必要があります。テーブルでの活動の大部分は読書です。日中に新しいデータがINSERTedされることを除いて、何も変更する必要はありません。

ユーザーは、単純なレコードのルックアップ要求から、さまざまな基準に基づいて数万行をプルするまで、さまざまなクエリをテーブルに対して実行します。実行されるクエリに対する制御は限られているため、インデックスを作成してもパフォーマンスが低下し始めています。

問題の大部分はディスクI/Oであり、SSDベースのアレイを改良することで対処しています。すべてのデータベースファイルがこの新しいアレイ上にあるため、複数のデータベースファイルを使用しても違いはないというコンセンサスはありますが、テーブルを個別のテーブルに分割するのが良い方法かもしれません。

私は今、これに対する最善のアプローチが何であるかについて困惑しています。私が自分で議論している2つのアイデア:

  1. テーブルを「層」に分割します

    • 先週のデータを含むテーブルです。
      INSERTed毎日
    • 先週から3か月前までの次のテーブル
    • 3ヶ月から6ヶ月を含む次のテーブル
    • 6か月以上経過したものを含む次のテーブル

    次に、データを一晩で「シャッフル」してデータベースにアクセスします(データベースには午前8時から午後10時までしかアクセスできないため、データを処理するためのウィンドウが一晩あります)。

  2. データ範囲のテーブルを作成します

    • データ範囲のテーブルを作成します(四半期ごとなど)。次に、データINSERTingをテーブル2Q2013に入れ、3Q2013、4Q2014などに移動します...

    これによりパフォーマンスが向上する場合は、ファイルグループを使用して古いテーブルを「読み取り専用」にすることができます。

オプション1は私が実装するのが最も簡単ですが、これが完全に狂ったアイデアであるかどうかはわかりません。オプション2は実装と保守がより多くの作業ですが、この種の問題の「ベストプラクティス」である場合、それが私がやる方法です。

あらゆるアドバイスや代替案はありがたく受け取られます-私はこれらの種類の問題が設計時に解決されるのが一番です。

5
KenD

私は個人的にあなたの最初のオプションを選びます。 「DELETE dbo.p1 OUTPUT INTO dbo.p2」パターンを使用してデータを移動する場合、失敗する可能性のある多くのものはありません。タイムフレーム内で250K x 3行をこのように移動しても、約10K行のバッチで移動しても問題はありません。

一般的なカレンダーベースのパーティション分割よりも優れている点は、「パーティション」が同じサイズのままであることです。カレンダーベースのパーティション分割アプローチを扱うデータの量が多いと、月の初めには非常にうまく機能し、月の終わりにはかなり遅くなる可能性があります。

私はKalen Delanyと一緒に、「古くなったパーティションからパーティションへデータを移動する」アプローチの利点について、しばらくsqlmagで記事を書きました: http://sqlmag.com/database-administration/using- table-partitions-archive-old-data-oltp-environments

この記事では、エンタープライズ専用の組み込みパーティション分割機能を使用していますが、手作りのマルチテーブルパーティション分割を使用して実装することもできます。

異なるテーブル(パーティション)を別々のドライブに配置しようと思います。古いパーティションのデータはダウンタイム中にのみ変更されるため、日中はこれらのファイルグループを読み取り専用としてマークすることもできます。または、TRANSACTION ISOLATION READ UNCOMMITTEDまたはREAD COMMITTED SNAPSHOT隔離。後者の場合も、実際にデータを更新しないことを前提として、「現在の」パーティションでも速度を上げる必要があります。しかし、更新があっても役立つ場合があります。どちらの方法でも、環境でパフォーマンスをテストしてください。 (どのような場合でも、クエリを読み取ると、使用しているデータ型によっては半分書き込まれた行が表示される可能性があるため、アクティブなテーブル/パーティションでUNCOMMITTEDを使用しないでください。)

3
Sebastian Meine

あなたの状況に対する私の最初の質問は、Standard Editionが与えられているかどうか、またはEnterpriseにアップグレードする可能性があるかどうかです。

SQL Server 2008 R2のEnterprise Editionでは、パーティションテーブルを使用できます。

基本的に、これらはバックグラウンドで手動プロセスとして記述したことを実行します。

1 からの引用:

パーティショニングを使用すると、データコレクションの整合性を維持しながら、データのサブセットをすばやく効率的に管理およびアクセスできるため、大きなテーブルまたはインデックスをより管理しやすくなります。パーティショニングを使用することにより、OLTPからOLAPシステムへのデータのロードなどの操作は、操作が以前にかかった分と時間ではなく、数秒しかかかりませんSQL Serverのバージョン。データのサブセットに対して実行されるメンテナンス操作は、テーブル全体ではなく、必要なデータのみを対象とするため、より効率的に実行されます。

[〜#〜] edit [〜#〜]は、エンタープライズはオプションではないと述べています:

Standard Editionを使用する場合、パーティションビューの使用にフォールバックできます。

使用方法との主な違いは、パーティションテーブルを自分で管理する必要があることと、すべての新しいメンバーテーブルをビューに追加する必要があることです。

アイデアはシナリオ2に基づいていますが、データを挿入する場所を気にする必要はありません。これは、メンバーテーブルのCHECK-Constraintsに基づくパーティションビューによって決定されるためです。

良い例については、 2 を参照してください

すべてのパーティション分割シナリオに関して、選択したパーティション分割列がクエリと挿入の動作に適合することを確認する必要があります。

5
Oliver Rahner