파티션 키를 업데이트하여 파티션간에 행을 이동할 수 있습니까?


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으로 변경하여 첫 번째 파티션에서 세 번째 파티션으로 행을 옮길 수 있습니까?

참고 :이 둘 다 파티셔닝을 지원하기 때문에 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
훌륭하게 해답입니다!
Marian

이는 SQL Server 2005에서도 설명 된대로 실행됩니다.
Ben Brocka

-1 시나리오를 테스트하지 않습니다. $PARTITION입력을 기반으로 파티션 번호 만 계산합니다. 실제로 행이 실제로 어디에 있는지 테스트하지 않습니다.
Jon Seigel

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를 쿼리하면 (2005 년에) 테이블에 테이블에 대해 하나가 아닌 두 개의 파티션이있는 것을 볼 수 있습니다. 이것은이 테이블에 대한 파티셔닝을 완전히 구현했음을 나타냅니다.

select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id 행
-------------------- ----------- ----------- -------- -------- -------------------- --------------------
72057597780295680 770674389 11 72057597780295680 0
72057597780361216 77067438912 72057597780361216 0

이제 두 개의 파티션 (각 행 수)이 있으므로 실험을 수행 할 수 있습니다.

행을 삽입

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 77067438912 72057597780361216 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 77067438912 72057597780361216 0

첫 번째 파티션에는 이제 1이 아닌 두 개의 행이 있고 두 번째 파티션에는 2가 아닌 0이 있습니다.

분할 된 테이블에서 클러스터 키를 수정 한 결과 행이 자동으로 이동되었음을 확인합니다.


1
실제로 시나리오를 테스트하는이 질문에 대한 첫 번째 답은 +1입니다. DBA.SE에 오신 것을 환영합니다!
Jon Seigel

-1 테이블을 '완전히'파티셔닝하기위한 요구 사항을 지원하는 MSDN 문서를 알려 주시겠습니까? 특히 별도의 파일 그룹과 클러스터 된 인덱스가 필요합니까?
Kenneth

-2

나는 그 대답이 옳다고 생각하지 않습니다. 값을 사용할 때

 $PARTITION.IDRange1([ID]) AS Partition

레코드가 현재있는 위치가 아니라 파티션의 위치를 ​​다시 계산하기 만하면됩니다.

다음을 사용해야합니다.

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

sql 2005에 대한 테스트에서 값이 변경되지만 레코드는 동일한 파티션에 유지됩니다. 파티션이 특정 범위에있을 것으로 예상하는 다중 스레드 모드에서 실행되므로 통계 및 옵티마이 저가 엉망이 될 수 있습니다. 파티션 제거를 사용하여 관련 파티션 만 쿼리하려고 할 때도 완전히 잘못됩니다. 이동하려면 각 레코드를 삭제하고 다시 삽입해야한다고 생각합니다.


2
$partition 여기에서 검색 하면 수락 된 답변이 올바른 것입니다. 레코드가 업데이트 된 후 동일한 파티션에 유지되는지 어떻게 확인합니까?
Nick Chammas

첫 번째 요점은 사실이지만 행이 움직이지 않는다는 결론은 거짓입니다. 아마도 실행 된 테스트에 문제가있을 수 있습니다.
Jon Seigel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.