SQL Server 이야기

Partitioned Table(분할된 테이블)에 대한 SPLIT/MERGE 방식의 이해

늘푸르른나 2014. 7. 11. 17:34

Partitioned Table(분할된 테이블)에 대해서 새로운 파티션 추가를 위해 SPLIT을 하거나 빈 파티션을 제거하기 위해 MERGE 작업을 수행할 때 잘못하면 파티션간에 Data Move가 발생하여 심각한 성능 문제를 유발할 수 있습니다. 이런 문제를 예방하기 위해 SQL Server 온라인 설명서 및 기타 White Paper에서는 다음과 같이 파티션 Range의 양 끝에 빈 파티션을 유지할 것을 권장하고 있으며 항상 MERGE SPLIT 작업은 빈 파티션에 대해서만 수행할 것을 권장하고 있습니다.

 

ALTER PARTITION FUNCTION (Transact-SQL)(http://technet.microsoft.com/en-us/library/ms186307(v=sql.110).aspx)

 

Always keep empty partitions at both ends of the partition range to guarantee that the partition split (before loading new data) and partition merge (after unloading old data) do not incur any data movement. Avoid splitting or merging populated partitions. This can be extremely inefficient, as this may cause as much as four times more log generation, and may also cause severe locking.

 

 

하지만, 실제 운영 환경에서는 관리 부주의나 불가피한 이유에 의해서 실제 데이터가 존재하는 파티션에 대해 SPLIT이나 MERGE 작업을 수행해야만 하는 경우가 발생할 수 있는데 이런 경우 Data Move가 발생하는지, Data Move가 발생한다면 얼마나 발생할지 등을 미리 알고 준비하여 작업을 수행해 줄 필요가 있습니다.

 

SPLIT 작업을 할 때 실제 Data Move가 발생하는지 여부에 대해서 다음의 Blog Article에서 꼼꼼하게 테스트한 결과를 참조해 볼 수 있습니다. Blog의 내용을 간단하게 요약하면 마지막 파티션에 데이터가 존재하더라도 RIGHT RANGE 파티션일 경우에는 Data Move가 발생하지 않을 수 있으나 LEFT RANGE 파티션일 경우에는 Data Move가 반드시 발생하게 된다는 것입니다.

 

When does SQL Server partition split move data?(http://davidpeterhansen.com/sql-server-partition-split/)

 

상기의 Blog에는 SPLIT 작업 시 Data Move 발생 여부에 대해 꼼꼼한 고찰은 되어 있으나 현상만을 확인하여 정리하였을 뿐 정확한 논리적인 근거가 없습니다. 정확한 테스트를 기반으로 정리하였으니 만큼 Blog의 내용이 맞는 것 같기는 한데 정확한 SQL Server의 동작 방식에 근거한 논리적인 설명이 부족한 느낌이 있는 것이 사실입니다. 이렇게 부족한 SPLIT MERGE 동작 방식에 대한 설명은 SQL Server 온라인 설명서로부터 확인할 수 있으며 그 내용 중 중요한 부분만을 발췌해 보면 다음과 같습니다.

 

ALTER PARTITION FUNCTION (Transact-SQL)(http://technet.microsoft.com/en-us/library/ms186307(v=sql.110).aspx)

 

SPLIT RANGE ( boundary_value )

Adds one partition to the partition function. boundary_value determines the range of the new partition, and must differ from the existing boundary ranges of the partition function. Based on boundary_value, the Database Engine splits one of the existing ranges into two. Of these two, the one where the new boundary_value resides is considered the new partition.

MERGE [ RANGE ( boundary_value) ]

Drops a partition and merges any values that exist in the partition into one of the remaining partitions. RANGE ( boundary_value) must be an existing boundary value, into which the values from the dropped partition are merged. The filegroup that originally held boundary_value is removed from the partition scheme unless it is used by a remaining partition, or is marked with the NEXT USED property. The merged partition resides in the filegroup that originally did not hold boundary_value.

 

 

상기의 내용으로부터 SPLIT MERGE의 동작 방식에 대해서 정확하게 이해할 수 있습니다. 정리하면, SPLIT 시에는 새로운 파티션이 하나 생성되는데 Boundary Value가 포함된 Range가 새로운 파티션에 할당되고 MERGE 시에는 두 개의 파티션 중 Boundary Value가 포함된 파티션이 삭제됩니다.

 

이런 동작 방식을 염두해 두면 SPLIT이나 MERGE Data Move가 발생할지 여부나 그 양을 가늠해 볼 수 있습니다. 예를 들어, RIGHT RANGE 파티션에서 Boundary Value를 기존에 저장되어 있는 모든 데이터보다 큰 값으로 지정하여 SPLIT을 수행하면 새롭게 추가된 Boundary Value가 새로운 파티션에 할당(Boundary Value <= 신규 파티션 Range)되므로 기존의 파티션에 있는 데이터의 이동이 발생하지 않습니다. 마찬가지로, RIGHT RANGE 파티션에서 첫 번째 파티션을 비우고(Switch Out) 두 번째 파티션과의 경계 값을 Boundary Value로 지정하여 MERGE를 수행하면 해당 Boundary Value는 두 번째 파티션에 속해 있으므로(Boundary Value <= 두 번째 파티션 Range < 다음 Boundary Value) Boundary Value가 속해 있는 두 번째 파티션이 삭제되게 되고 이로 인해 두 번째 파티션에 있던 모든 데이터가 첫 번째 파티션으로 이동하게 됩니다.

 

따라서, RIGHT RANGE 파티션의 경우에는 MERGE를 위해서 반드시 첫 번째 파티션은 항상 비워두어야만 불필요한 Data Move를 예방할 수 있으며 SPLIT을 위해서는 맨 마지막 파티션을 비워두지 않아도 신규 Boundary Value만 기존에 저장된 데이터보다 큰 값으로 지정하기만 하면 Data Move 없이 SPLIT 작업을 수행할 수 있습니다. 이와는 반대로 LEFT RANGE 파티션의 경우에는 MERGE를 위해서 첫 번째 파티션을 항상 비워 두지 않아도 Data Move 없이 MERGE 작업을 수행할 수 있으며 SPLIT을 위해서는 맨 마지막 파티션을 항상 비워두어야만 불필요한 Data Move를 예방할 수 있습니다.

 

하지만, 파티션 Range의 양 끝에 빈 파티션을 유지하면 RIGHT RANGE 파티션인지 LEFT RANGE 파티션인지 여부에 관계 없이 SPLIT이나 MERGE 작업 수행 시 Data Move가 발생하지 않도록 할 수 있으므로 SQL Server 온라인 설명서나 White Paper에서 권고하는 대로 파티션 Range의 양 끝에 빈 파티션을 유지하고 MERGE SPLIT 작업은 항상 빈 파티션에 대해서만 수행하는 것이 좋습니다.