Bisakah saya memindahkan baris antar partisi dengan memperbarui kunci partisi?


17

Saya akan berpikir bahwa ini akan menjadi pertanyaan yang cukup sederhana, tetapi saya sebenarnya mengalami kesulitan menemukan jawaban untuk ini.

Pertanyaannya: Bisakah Anda memindahkan baris data dalam tabel yang dipartisi dari satu partisi ke partisi lain hanya dengan memperbarui kolom partisi sehingga melewati batas partisi?

Misalnya, jika saya memiliki tabel yang memiliki kunci partisi:

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

Dengan fungsi partisi yang memetakan ke kunci utama:

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

Bisakah saya memindahkan baris dari partisi pertama ke partisi ketiga dengan mengubah SampleID dari 1 menjadi (katakanlah) 500.000?

Catatan: Saya menandai ini sebagai sql server 2005 dan 2008, karena keduanya mendukung partisi. Apakah mereka menanganinya secara berbeda?

Jawaban:


14

Saya tidak punya server 2005 untuk diuji. Namun 2008, tampaknya menangani ini seperti yang diharapkan:

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 ;

Anda akan melihat satu catatan di setiap partisi sebelum pembaruan, dan kedua catatan di partisi pertama sesudahnya.


1
itu jawaban yang bagus!
Marian

Ini dijalankan seperti yang Anda gambarkan dalam SQL Server 2005 juga
Ben Brocka

-1 Ini tidak menguji skenario. $PARTITIONhanya menghitung nomor partisi berdasarkan input; itu tidak benar-benar menguji di mana barisan secara fisik hidup.
Jon Seigel

9

Untuk menguji ini, percobaan sebenarnya perlu mempartisi tabel. Lihat http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx

Meminta fungsi partisi hanya memberi tahu Anda apa yang dikatakan fungsi partisi. Tidak disebutkan di mana data disimpan. Anda dapat mengatur fungsi partisi dan menjalankannya tanpa benar-benar mempartisi tabel, seperti yang telah ditunjukkan di sini.

Untuk mempartisi tabel, Anda juga harus membuat grup file dan skema partisi yang menggunakan fungsi partisi untuk menetapkan hasil fungsi ke grup file. Maka Anda harus meletakkan kunci berkerumun di tabel yang menggunakan skema partisi itu.

Siapkan partisi

Saya bukan ahli dalam baris perintah SQL. Saya menggunakan antarmuka SSMS untuk mengatur grup file pfg1 (dengan file pf1) dan pfg2 (dengan file pf2). Lalu saya mendeklarasikan fungsi dan skema partisi:

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

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

Buat tabel dan indeks berkerumun

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

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

Setelah Anda melakukan ini, ketika Anda kueri sys.partitions (I have 2005), Anda melihat bahwa tabel sekarang memiliki dua partisi bukan hanya satu untuk tabel. Ini menunjukkan bahwa kami telah mengimplementasikan partisi sepenuhnya untuk tabel ini.

select * from sys.partitions where object_id = object_id('IDRanges')
partisi_id object_id index_id partisi_number baris hobt_id
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0

Sekarang kami memiliki dua partisi (dengan jumlah baris untuk masing-masing), kami dapat melakukan percobaan.

Masukkan baris

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

Periksa partisi sys.art untuk melihat apa yang terjadi.

select * from sys.partitions where object_id = object_id('IDRanges')
partisi_id object_id index_id partisi_number baris hobt_id
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1

Ya. Satu baris di setiap partisi.

Pindahkan satu baris.

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

Periksa partisi

select * from sys.partitions where object_id = object_id('IDRanges')
partisi_id object_id index_id partisi_number baris hobt_id
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0

Partisi pertama sekarang memiliki dua baris, bukan 1, dan partisi kedua memiliki nol baris, bukan dua.

Saya pikir ini menegaskan bahwa baris secara otomatis dipindahkan sebagai hasil dari memodifikasi kunci yang dikelompokkan dalam tabel dipartisi.


1
+1 untuk jawaban pertama untuk pertanyaan ini yang benar-benar menguji skenario. Selamat datang di DBA.SE!
Jon Seigel

-1 Dapatkah Anda mengarahkan saya ke dokumen MSDN yang mendukung persyaratan Anda untuk 'sepenuhnya' mempartisi tabel? Khususnya perlunya kelompok file yang terpisah dan indeks berkerumun?
Kenneth

-2

Saya kira jawabannya tidak benar. Ketika Anda menggunakan nilai

 $PARTITION.IDRange1([ID]) AS Partition

Anda hanya menghitung ulang apa yang seharusnya menjadi partisi, bukan di mana catatan saat ini.

Kamu harus menggunakan:

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

Dalam pengujian saya pada sql 2005 nilai berubah tetapi catatan tetap di partisi yang sama. Ini mungkin akan mengacaukan statistik dan optimizer karena akan berjalan dalam mode multi-threaded mengharapkan partisi berada dalam kisaran tertentu. Ini juga akan sepenuhnya salah ketika mencoba menggunakan penghapusan partisi untuk hanya menanyakan partisi yang relevan. Saya pikir Anda perlu menghapus dan memasukkan kembali setiap catatan untuk membuatnya dipindahkan.


2
Mencari $partition di sini menunjukkan bahwa jawaban yang diterima benar. Bagaimana Anda mengonfirmasi bahwa rekaman tetap berada di partisi yang sama setelah diperbarui?
Nick Chammas

Poin pertama benar, tetapi kesimpulan bahwa baris tidak bergerak adalah salah - mungkin ada sesuatu yang salah dengan tes yang dijalankan.
Jon Seigel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.