web-dev-qa-db-ja.com

SQL Server 2012での大きなテーブルとアーカイブのための優れた戦略

1日あたり約500,000行が追加されるテーブルがあります。データベースは、OLTPシステムをサポートしています。その構成は、次のようになります。

create table Stuff 
(StuffID int identity not null primary key,  
ValueA decimal(18,4) not null,   
ValueB decimal(18,4) not null,  
ValueC decimal(18,4) not null,   
ValueD decimal(18,4) not null,  
StuffName varchar(10) not null,   
Created datetime not null default(getdate())  )

実行するクエリの種類が原因で、カバリングインデックスがあります。

通常、私は当日のデータのみを処理しています。主キーをターゲットにしているクエリはほとんどありません。クラスター化インデックスを主キーから作成日(日時)列に移動することを検討してきました。これは、クエリの多くがそれに基づいており、通常、結果セットを時系列で表示したいためです。

機能の観点からはそれを移動する理由がないので、すべてを1つのテーブルに保持したいのですが、あるタイプのアーカイブ戦略がなく、最終的には「多すぎる」行が含まれることになるのではないかと心配しています。そこ。 5年間で10億レコードになるはずですが、テーブルのデータサイズが比較的小さいことを考えると、これは大した問題ではないかもしれません。

要約すると、1日あたり500K行が追加される小さなデータサイズのテーブルの場合、特に注意すべき戦略はありますか?サイズが原因で一般的な速度低下が発生しますか、それとも心配する必要はありませんか?

1
Eric

うまくいけば、そのサイズであなたはエンタープライズ版にいますか?そうでない場合、幸運:)(冗談は答えの下部を参照してください)

Enterpriseを使用している場合は、パーティション分割を検討することをお勧めします。これにより、この同じ種類のシナリオを処理するときに、私の尻を1〜2時間節約できました。日付フィールドにパーティションを作成すると、それらのパーティションの大きさを最も適切に決定する必要があります。 1日に1つのパーティションを作成し、1か月に1つのパーティションを作成しました。それはすべて、必要な履歴の量に依存します(テーブルごとのパーティション数に設定された制限のみが適用されることに注意してください)。

パーティションを1日に制限し、クエリが特定の日のみである場合、オプティマイザはパーティション削除を使用して、クエリに必要なパーティションのみを選択できる必要があります。また、数年後に古いデータを削除する時期が来た場合、パーティションのスライドにより、(削除ステートメントではなく)データを本当に簡単にすばやく削除できます。古いデータを別のテーブルに完全にアーカイブする場合も同様です。

非エンタープライズのアイデア:
別のテーブルへのアーカイブといえば、これも役立ち、エンタープライズを必要としません。このテーブルが1か月または1年より古いものの読み取りにのみ使用されている場合、次のことができます。
1)Stuff_Archiveという名前の2番目のテーブルを作成します
2)1か月または1年より古いものすべてを移動します(好み)
3)現在のStuffテーブルの名前をStuff_Currentに変更します
4)Stuff_CurrentとStuff_Archiveを結合したStuffという名前のビューを作成します。このようにして、Stuffを使用するすべてのアプリケーションは引き続き両方から読み取ることができます。クエリを変更して、Stuffをオフにすることができます。

さらに役立つかもしれないと思うのは、レコードをStuff_Archiveに移動するたびに変更する必要がある制約を追加することです(これはテストしていませんが、現在このように維持する必要があるDBで試す予定です) )。この制約は日付フィールドにあるので、オプティマイザーは「わかりました。これらの2つのテーブルを結合している場合でも、XとYとテーブルの間の日付を要求している場合は、実際にはテーブルAだけを見る必要があります。 YとZの間の日付を要求する場合はB」理論的には、列/インデックスの統計がオプティマイザにすでに通知していると想定しますが、制約が役立つかどうか(繰り返しますが、テストする時間はありませんでした)といつも思っていました。

また、エンタープライズ以外のアイデアとして、日付フィールドに非クラスター化インデックスを作成し、さらにそれを(メンテナンスウィンドウに適合させることができる場合は)フィルター付きインデックスを作成することもできます。dt> = somedate in a past and dt <= somedate将来は。そうすることで、作成したクエリはフィルターされたインデックスを使用でき、そのデータはその日付範囲内のデータと同じ大きさになります(成長するテーブルにあるすべての履歴ではなく)。つまり、1週間のフィルター処理されたインデックスを作成すると、50億レコードではなく、500k * 7 = 3.5mレコードのみが処理されます。クエリのタイムフレーム内のフィルターされたwhere基準で説明されているそのウィンドウを維持するのに十分な頻度でそのインデックスを再構築する必要があります。ですから、毎日それを再構築でき、昨日のデータだけが必要な場合は、すばらしいです。ただし、週末にのみ再構築できる場合は、統計が週を通して最新に保たれるようにする必要があります。

3
Chris Woods

データアクセスパターンに少し依存します。順次書かれていると思います。本当?読み込みはどうですか?順次かランダムか?

すべてがシーケンシャルであり、堅牢なI/Oパイプがある場合は問題ありません。ランダムな場合、またはI/O設定が不十分な場合は、データをアーカイブせずに問題が発生します。

ハードウェアの詳細は提供していないので、VLDBの経験が11年以下であることに基づいて、膨大な数の仮定を立てています。

0
user41207