パーティションキーを更新して、パーティション間で行を移動できますか?


17

これはかなり単純な質問だと思いますが、実際にはこれに対する答えを見つけるのに苦労しました。

質問:パーティション列を更新してパーティションの境界を越えるだけで、パーティションテーブル内のデータ行をあるパーティションから別のパーティションに移動できますか?

たとえば、パーティションキーを持つテーブルがある場合:

CREATE TABLE SampleTable
(
    SampleID INT PRIMARY KEY,
    SampleResults VARCHAR(100) NOT NULL,
)

主キーにマップするパーティション関数を使用して:

CREATE PARTITION FUNCTION MyPartitionFunc (INT) AS
RANGE LEFT FOR VALUES (10000, 20000);

SampleIDを1から(たとえば)500,000に変更して、最初のパーティションから3番目のパーティションに行を移動できますか?

注:どちらもパーティション分割をサポートしているため、SQL Server 2005と2008の両方としてこれをタグ付けしています。彼らはそれを異なって扱いますか?

回答:


14

テストする2005サーバーはありません。ただし、2008年はこれを予想どおりに処理しているようです。

USE [Test]
GO
CREATE TABLE [IDRanges](
    [ID] [int] NOT NULL
)
GO

CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT] 
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID]) 
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT] 
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID]) 
ORDER BY Partition ;

更新前に各パーティションに1つのレコードが表示され、その後最初のパーティションに両方のレコードが表示されます。


1
それはうまくできた答えです!
マリアン

これは、SQL Server 2005で説明したとおりに実行されます
ベンBrocka

-1これはシナリオをテストしません。$PARTITION入力に基づいてパーティション番号のみを計算します。行が物理的にどこにあるかは実際にはテストされません。
ジョンザイゲル

9

これをテストするには、実験で実際にテーブルを分割する必要があります。http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspxを参照してください

パーティション関数を照会すると、パーティション関数が何を言っているかがわかります。データがどこに保存されているかはわかりません。ここで既に示したように、実際にテーブルをパーティション化することなく、パーティション関数を設定して実行できます。

テーブルを分割するには、ファイルグループと、パーティション関数を使用して関数結果をファイルグループに割り当てるパーティションスキームも作成する必要があります。次に、そのパーティションスキームを使用するテーブルにクラスター化キーを配置する必要があります。

パーティショニングを設定する

私はコマンドラインSQLの専門家ではありません。SSMSインターフェイスを使用して、ファイルグループpfg1(pf1ファイル)とpfg2(pf2ファイル)をセットアップしました。次に、パーティション関数とスキームを宣言しました。

CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO

CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO

テーブルとクラスター化インデックスを作成する

CREATE TABLE [IDRanges](
    [ID] [int] NOT NULL
)
GO

CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO

これを行った後、sys.partitions(I have 2005)を照会すると、テーブルに1つだけではなく2つのパーティションがあることがわかります。これは、このテーブルのパーティショニングが完全に実装されたことを示しています。

select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id行
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0

2つのパーティション(それぞれに行数がある)ができたので、実験を行うことができます。

行を挿入する

INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)

sys.partitionsをチェックして、何が起こったかを確認してください。

select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id行
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1

うん。各パーティションに1行。

行を移動します。

UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17

パーティションを確認する

select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id行
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0

最初のパーティションには1ではなく2つの行があり、2番目のパーティションには2ではなくゼロの行があります。

これは、パーティションテーブルのクラスター化キーを変更した結果、行が自動的に移動されたことを確認していると思います。


1
シナリオを実際にテストするこの質問に対する最初の回答に対して+1。DBA.SEへようこそ!
ジョンセイゲル

-1テーブルを「完全に」パーティション分割するための要件をサポートするMSDNドキュメントを教えていただけますか?具体的には、個別のファイルグループとクラスター化インデックスが必要ですか?
ケネス

-2

その答えは正しいとは思いません。値を使用する場合

 $PARTITION.IDRange1([ID]) AS Partition

レコードが現在どこにあるかではなく、パーティションがどうあるべきかを単に再計算しています。

以下を使用する必要があります。

select * from sys.partitions where object_id = object_id('IDRanges')

SQL 2005でのテストでは、値は変わりますが、レコードは同じパーティションに残ります。パーティションが特定の範囲内にあることを期待してマルチスレッドモードで実行されるため、これはおそらく統計とオプティマイザーを混乱させます。また、パーティション削除を使用して関連するパーティションのみを照会しようとすると、完全に間違ってしまいます。移動するには、各レコードを削除して再挿入する必要があると思います。


2
$partition ここで検索すると、受け入れられた答えが正しいことが示唆されます。レコードが更新された後、同じパーティションに残っていることをどのように確認していますか?
ニックチャマス

最初の点は真ですが、行が移動しないという結論は偽です。実行されたテストに何か問題があると思われます。
ジョンセイゲル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.