Tôi có thể di chuyển các hàng giữa các phân vùng bằng cách cập nhật khóa phân vùng không?


17

Tôi nghĩ rằng đây sẽ là một câu hỏi khá đơn giản, nhưng tôi thực sự đã có một thời gian khó khăn để tìm một câu trả lời cho điều này.

Câu hỏi: Bạn có thể di chuyển các hàng dữ liệu trong một bảng được phân vùng từ phân vùng này sang phân vùng khác bằng cách cập nhật cột phân vùng để nó vượt qua ranh giới phân vùng không?

Ví dụ: nếu tôi có một bảng có khóa phân vùng:

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

Với chức năng phân vùng ánh xạ tới khóa chính:

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

Tôi có thể di chuyển một hàng từ phân vùng thứ nhất sang phân vùng thứ ba bằng cách thay đổi SampleID từ 1 thành (500) không?

Lưu ý: Tôi gắn thẻ này là cả máy chủ sql 2005 và 2008, vì cả hai đều hỗ trợ phân vùng. Họ có xử lý nó khác nhau không?

Câu trả lời:


14

Tôi không có máy chủ năm 2005 để kiểm tra. Tuy nhiên, năm 2008 dường như xử lý việc này như mong đợi:

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 ;

Bạn sẽ thấy một bản ghi trong mỗi phân vùng trước khi cập nhật và cả hai bản ghi trong phân vùng đầu tiên sau đó.


1
đó là một câu trả lời được thực hiện độc đáo!
Mary

Điều này cũng được thực thi như bạn mô tả trong SQL Server 2005
Ben Brocka

-1 Điều này không kiểm tra kịch bản. $PARTITIONchỉ tính số phân vùng dựa trên đầu vào; nó không thực sự kiểm tra nơi hàng sống.
Jon Seigel

9

Để kiểm tra điều này, thí nghiệm thực sự cần phân vùng bảng. Xem http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx

Truy vấn chức năng phân vùng chỉ cho bạn biết chức năng phân vùng nói gì. Nó không nói nơi dữ liệu được lưu trữ. Bạn có thể thiết lập chức năng phân vùng và chạy nó mà không thực sự phân vùng bảng, như đã được chứng minh ở đây.

Để phân vùng bảng, bạn cũng phải tạo các nhóm tệp và sơ đồ phân vùng sử dụng chức năng phân vùng để gán kết quả chức năng cho các nhóm tệp. Sau đó, bạn phải đặt một khóa cụm trên bảng sử dụng sơ đồ phân vùng đó.

Thiết lập phân vùng

Tôi không phải là chuyên gia về dòng lệnh SQL. Tôi đã sử dụng giao diện SSMS để thiết lập các nhóm tệp pfg1 (với tệp pf1) và pfg2 (với tệp pf2). Sau đó, tôi đã khai báo hàm và lược đồ phân vùng:

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

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

Tạo bảng và chỉ mục cụm

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

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

Sau khi bạn làm điều này, khi bạn truy vấn sys.partitions (Tôi có 2005), bạn sẽ thấy rằng bảng hiện có hai phân vùng thay vì chỉ một cho bảng. Điều này chỉ ra rằng chúng tôi đã thực hiện đầy đủ phân vùng cho bảng này.

select * from sys.partitions where object_id = object_id('IDRanges')
phân vùng_id object_id index_id phân vùng_number hobt_id hàng
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0 0
72057597780361216 770674389 1 2 72057597780361216 0 0

Bây giờ chúng tôi có hai phân vùng (với số lượng hàng cho mỗi), chúng tôi có thể tiến hành một thử nghiệm.

Chèn các hàng

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

Kiểm tra sys.partitions để xem những gì đã xảy ra.

select * from sys.partitions where object_id = object_id('IDRanges')
phân vùng_id object_id index_id phân vùng_number hobt_id hàng
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1

Vâng. Một hàng trong mỗi phân vùng.

Di chuyển một hàng.

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

Kiểm tra các phân vùng

select * from sys.partitions where object_id = object_id('IDRanges')
phân vùng_id object_id index_id phân vùng_number hobt_id hàng
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0 0

Phân vùng đầu tiên bây giờ có hai hàng thay vì 1 và phân vùng thứ hai có 0 hàng thay vì hai.

Tôi nghĩ rằng điều này xác nhận rằng hàng đã được tự động di chuyển do sửa đổi khóa được nhóm trong một bảng được phân đoạn.


1
+1 cho câu trả lời đầu tiên cho câu hỏi này thực sự kiểm tra kịch bản. Chào mừng đến với DBA.SE!
Jon Seigel

-1 Bạn có thể vui lòng chỉ cho tôi các tài liệu MSDN hỗ trợ các yêu cầu của bạn để 'phân vùng' đầy đủ một bảng không? Cụ thể sự cần thiết cho các nhóm tệp riêng biệt và một chỉ mục cụm?
Kenneth

-2

Tôi không nghĩ rằng câu trả lời là đúng. Khi bạn sử dụng giá trị

 $PARTITION.IDRange1([ID]) AS Partition

bạn chỉ đơn giản là tính toán lại phân vùng nên là gì, không phải là bản ghi hiện tại.

Bạn nên sử dụng:

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

Trong các thử nghiệm của tôi trên sql 2005, giá trị thay đổi nhưng bản ghi vẫn nằm trong cùng một phân vùng. Điều này có thể sẽ gây rối với các số liệu thống kê và trình tối ưu hóa vì nó sẽ chạy trong chế độ đa luồng, mong muốn phân vùng nằm trong một phạm vi cụ thể. Nó cũng sẽ hoàn toàn sai khi nó cố gắng sử dụng loại bỏ phân vùng để chỉ truy vấn phân vùng có liên quan. Tôi nghĩ bạn cần xóa và chèn lại từng bản ghi để khiến chúng di chuyển.


2
Tìm kiếm $partition ở đây cho thấy câu trả lời được chấp nhận là chính xác. Làm thế nào để bạn xác nhận rằng bản ghi vẫn ở trong cùng một phân vùng sau khi nó đã được cập nhật?
Nick Chammas

Điểm đầu tiên là đúng, nhưng kết luận rằng hàng không di chuyển là sai - có lẽ có gì đó không đúng với bài kiểm tra đã được chạy.
Jon Seigel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.