web-dev-qa-db-ja.com

SQL Server 2012のパーティションでテーブルパージを実装する方法は?

私はこの質問を読みました: テーブルパーティションを削除する方法

しかし、それは私が望むものではありません。

1か月のパーティションを持つように日付/時刻列のパーティション分割を使用して、テーブルをセットアップしたいと思います。その後、montlhyを実行し、9か月以上前のレコードを持つパーティションを削除するジョブを構成します。

SQL Server 2012 Enterpriseを使用してこれをセットアップできますか?

4
Ozzie

目標は、メタデータを更新するだけでトランザクションログの量を減らすことです。

データがパーティションから移動または削除されると、行が挿入および削除され、トランザクションログにLOB_INSERT_ROWSおよびLOB_DELETE_ROWが(トン単位で)生成されます。

唯一のオプションはパーティションを切り捨てることですが、このオプションは存在しません。空のパーティションでMergeSplitを使用するだけでそれを回避できます。

以下のサンプルでは、​​物事を短くして、過去3か月(つまり、8月、9月、10月)のデータのみを作成しますが、9か月まで簡単に拡張できます。 8月は、11月などにデータが追加され始めると削除されます。

ファイルとファイルグループの作成:

まず、6つのファイルとファイルグループ[Part_0]〜[Part_5]を作成します。

Alter Database [Test] Add Filegroup [Part_0];
...
Alter Database [Test] Add Filegroup [Part_5];
Alter Database [Test] Add File( NAME = N'Part_0', FILENAME = N'...\Part_0.ndf' , SIZE = 100MB , FILEGROWTH = 100MB ) TO Filegroup [Part_0];
...
Alter Database [Test] Add File( NAME = N'Part_5', FILENAME = N'...\Part_5.ndf' , SIZE = 100MB , FILEGROWTH = 100MB ) TO Filegroup [Part_5];

Create Function and Scheme:

Create Partition Function [DateKeyPartFunction] (datetime2)
as Range Right For Values ('20150801', '20150901', '20151001', '20151101', '20151201');
Create Partition Scheme [DateKeyPartScheme] as Partition [DateKeyPartFunction]
To ([Part_0], [Part_1], [Part_2], [Part_3], [Part_4], [Part_5]);

再び6つのパーティションがあります。これについては後で説明しますが、これは主に空のパーティションが必要なためです。

テーブルとクラスター化インデックスの作成:

テーブルの正確なデザインがわからないので、次のテーブルで作業します。

Create Table dbo.DataPart(id int identity(0, 1), name char(1000), name_date datetime2);

そしてこれClustered Index

Create Clustered Index IDX_Part On dbo.DataPart(name_date) On DateKeyPartScheme(name_date);

ダミーデータ:

このコードは、10月から8月(現在)までの6秒ごとのダミー日付の範囲で100万を超えるレコードを作成します。

With inc(n) as(
    Select ROW_NUMBER() over(order by (select 1))-1 From (
        Select 1 From (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x1(n)
        Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x2(n)
        Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x3(n)
        Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x4(n)
        Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x5(n)
        Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x6(n)
    ) as x(n)
)
Insert into dbo.DataPart(name, name_date) 
Select TOP(1000000) '', DATEADD(second, -n*6, getdate()) From inc;

分割データ:

これは次のように分割されます:

Id Partition    Left Bound      Right Bound     Row Count
1  [Part_0]                 < '20150801'    0
2  [Part_1] >= '20150801'   < '20150901'    184042
3  [Part_2] >= '20150901'   < '20151001'    432000
4  [Part_3] >= '20151001'   < '20151101'    383958
5  [Part_4] >= '20151101'   < '20151201'    0
6  [Part_5] >= '20151201'                   0
  • [Part_1]、[Part_2]、[Part_3]には、8月、9月、10月のデータが含まれています。
  • [Part_0](つまり、<'20150801')が存在するのは、11月に1回[Part_1](8月)を空にする前に空のパーティションが必要だからです。 7月以前のデータですが、空のままにしておく必要があります。
  • 11月に到達するまで空のままですが、来月は空のパーティションを簡単に作成できます。これが11月の[Part_4]の目的です。
  • パーティション構成では、正しい境界の外側にあるすべてのものに対して追加のパーティションが必要です。これは12月以降の[Part_5]であり、空のままにする必要があります。

11月を追加:

11月になると、新しい行は[Part_4]に移動し、8月のデータは[Part_1]から削除できます。数十万行を削除せずにそれを削除する唯一の方法は、[Part_1]をテーブルから移動することです。

Create Table dbo.DataPart_Temp(id int identity(0, 1), name char(1000), name_date datetime2);
Create Clustered Index IDX_Part_temp On dbo.DataPart_temp(name_date) On [Part_1];
Alter Table DataPart Switch Partition 2 to DataPart_temp Partition 1;
  • DataPart_TempDataPart(列、インデックス)と同一である必要があります
  • [Part_1]はDataPartからDataPart_tempに移動するため、DataPart_tempのクラスター化インデックスは同じファイルグループに作成する必要があります:[Part_1]
  • [Part_1]はDataPartの2番目のパーティションであり、DataPart_tempの最初の唯一のパーティションに切り替えられます。 8月のすべての行がDataPart_tempに入りました。

テーブルは次のようにパーティション化されます。

id Partition    Left Bound      Right Bound     Row Count
1  [Part_0]                 < '20150801'    0
2  [Part_1] >= '20150801'   < '20150901'    0
3  [Part_2] >= '20150901'   < '20151001'    432000
4  [Part_3] >= '20151001'   < '20151101'    383958
5  [Part_4] >= '20151101'   < '20151201'    0
6  [Part_5] >= '20151201'                   0

パーティションのマージ:

[Part_0]と[Part_1]は空になり、マージできるようになります。

Alter Partition Function [DateKeyPartFunction]() Merge Range ('20150801');

[Part_1]が削除されました:

id Partition    Left Bound      Right Bound     Row Count
1  [Part_0]                 < '20150901'    0
2  [Part_2] >= '20150901'   < '20151001'    432000
3  [Part_3] >= '20151001'   < '20151101'    383958
4  [Part_4] >= '20151101'   < '20151201'    0
5  [Part_5] >= '20151201'                   0

翌月追加:

[Part_1]は使用されなくなったので、次に使用可能なパーティションとしてパーティションスキームに追加できます。

Alter Partition Scheme [DateKeyPartScheme] Next Used [Part_1];

そして、[Part_5](12月、> = '20151201')は分割できます。

Alter Partition Function [DateKeyPartFunction]() Split Range ('20160101');

[Part_5]は空なので、移動する必要はありません。 [Part_5]の残りの半分は、次の使用可能なパーティションである[Part_1]に移動します。

Id Partition    Left Bound      Right Bound     Row Count
1  [Part_0]                 < '20150901'    0
2  [Part_2] >= '20150901'   < '20151001'    432000
3  [Part_3] >= '20151001'   < '20151101'    383958
4  [Part_4] >= '20151101'   < '20151201'    x rows in November
5  [Part_5] >= '20151201'   < '20160101'    0
6  [Part_1] >= '20160101'                   0

クリーンアップ:

DataPart_tempを切り捨ててから削除できるようになりました(または少なくともクラスタ化インデックスを削除できます)。

次の月を追加:

12月に、パーティションID 2を移動し([Part_2])、パーティション1とマージしてから、1月の分割前に追加し直す必要があります。

このプロセスを自動化するには、パーティション2のファイルグループの名前を探す必要があります。

そして、次の目的で動的SQLを作成します。

  • [Part_X]のDataPart_tempにクラスター化インデックスを追加(DataPartと同様)
  • [Part_X]をDataPartからDataPart_tempに切り替える
  • パーティション1と2のマージ
  • [Part_X]をDataPartに追加
  • 最後のパーティションを分割する
  • DataPart_tempを切り捨て
  • DataPart_tempまたはそのクラスター化インデックスを削除する

Fn_dblogを使用すると、トランザクションログが最小限であることがわかります。

5