클러스터형 인덱스를 다시 작성하면 왜 데이터 크기가 축소됩니까?


10

약 15GB의 데이터가 있고 테이블 크기가 5GB로 줄어든 테이블에서 클러스터 된 인덱스를 다시 작성하면 어떻게 될 수 있습니까? 어떤 종류의 "데이터"가 제거됩니까?

데이터 크기 i는 DBCC sp_spaceused의 "데이터"열을 의미합니다

클러스터형 인덱스에서 다시 작성하기 전에 :

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    39169656 KB 15857960 KB 22916496 KB 395200 KB

클러스터형 인덱스에서 재구성 후 :

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    29076736 KB 5867048 KB  22880144 KB 329544 KB

재 구축을위한 TSQL :

USE [DAX5TEST]
GO
ALTER INDEX [I_212RECID] ON [dbo].[LEDGERJOURNALTRANS] REBUILD PARTITION = ALL WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, ONLINE = ON, SORT_IN_TEMPDB = OFF, DATA_COMPRESSION = PAGE, FILLFACTOR = 85 )
GO

파일 크기에서 데이터 크기를 결정하고 있습니까?
JNK

데이터 크기는 내가 "데이터"를 의미 DBCC의 열은 sp_spaceused를
다니엘 비요크에게

이는의 "데이터"열입니다 EXEC sp_spaceused.
RLF

1
모든 본문에서 OP가 재구성 스크립트에서 페이지 압축 = 사용을 사용하고 있다는 것을 놓쳤으며 이전에는 그렇지 않은 것 같습니다. 다니엘 확인할 수 있습니까?
Shanky

1
@ Shanky : 그 ALTER INDEX진술은 코드에 의해 생성 된 것처럼 보이며 (기본 설정에 많은 옵션이 포함되어 있기 때문에) 기존 색인 옵션에서 작성된 것으로 의심됩니다. 그러나 당신이 옳습니다 : 이것이 실행되기 전에 클러스터형 인덱스에서 압축 활성화 되지 않았다면 데이터 풋 프린트의 감소를 대부분 설명 할 것입니다. (다니엘, 당신은 어느 쪽이든 다른 쪽을 확인할 수 있습니까?)
David Spillett

답변:


16

테이블에 클러스터 된 인덱스가있는 경우 인덱스 테이블 데이터입니다 (그렇지 않으면 힙 유형 테이블이 있음). 클러스터형 인덱스를 다시 빌드하면 (실제로 인덱스는 있지만 비 클러스터형 인덱스의 경우 공간이 "데이터"로 계산되지 않음) 부분적으로 사용 된 페이지가보다 완전한 형식으로 병합됩니다.

인덱스 순서로 인덱스 (클러스터 또는 기타)에 데이터를 삽입하면 필요에 따라 리프 페이지가 만들어지고 끝 부분에 하나의 부분 페이지 만있게됩니다. 색인 순서를 벗어난 데이터를 입력 할 때 데이터가 올바른 위치에 맞도록 페이지를 분할해야합니다. 두 페이지가 반 정도 찼고 새 행이 그 중 하나로갑니다. 시간이 지남에 따라 이것은 상당한 양의 여분의 공간을 소비하지만, 미래의 인서트가 약간의 틈새를 채울 수는 있지만 많은 일이 발생할 수 있습니다. 리프가 아닌 페이지도 비슷한 효과를 볼 수 있지만 실제 데이터 페이지의 크기는 훨씬 더 중요합니다.

또한 삭제하면 부분 페이지가 발생할 수 있습니다. 페이지에서 모든 행을 제거하면 "미사용"으로 계산되지만 하나 이상의 데이터 행이 남아 있으면 여전히 사용중인 것으로 계산됩니다. 한 페이지에 10 바이트를 사용하는 행이 하나만 있어도 해당 페이지는 사용 된 공간 수에서 8192 바이트로 계산됩니다. 다시 미래의 인서트는 약간의 차이를 채울 수 있습니다.

가변 길이 행의 경우 업데이트에도 동일한 효과가있을 수 있습니다. 행이 작아 질수록 페이지에 공간이 남게되어 나중에 다시 사용하기가 쉽지 않을 수 있으며 거의 ​​전체 페이지의 행이 길어지면 페이지 분할이 발생할 수 있습니다 .

SQL Server는 가비지 수집 연습이 성능 악몽 일 수 있으므로 인덱스 다시 작성 순서와 같이 명시 적으로 지시 될 때까지 페이지 사용 방식을 다시 정렬하여 데이터를 정규화하는 데 시간을 소비하지 않습니다.

나는 이것이 당신이보고있는 것으로 생각하지만, 데이터에 절대적으로 필요한 양의 ~ 2.7 배에 충분한 공간을 할당하는 것이 특히 나쁜 경우라고 말하고 싶습니다. 인덱스의 중요한 키 중 하나 (UUID 열) 중 하나 인 임의의 항목이 있음을 의미 할 수 있습니다. 즉, 새 행이 인덱스 순서로 추가 될 가능성이 적거나 최근에 상당한 수의 삭제가 발생했음을 의미합니다.

페이지 분할 예

페이지에 4 개가 고정 된 고정 길이 행이있는 색인 순서로 삽입 :

Start with one empty page: 
        [__|__|__|__]
Add the first item in index order:
        [00|__|__|__]
Add the next three
        [00|02|04|06]
Adding the next will result in a new page:
        [00|02|04|06] [08|__|__|__]
And so on...
        [00|02|04|06] [08|10|12|14] [16|18|__|__]

색인 순서에서 행을 추가하는 경우 (이것은 위의 짝수 만 사용하는 이유입니다) : 추가 11는 두 번째 페이지를 확장하거나 (고정 된 크기이므로 불가능) 11을 1 이상 위로 옮기는 것을 의미합니다 (너무 비쌉니다) 큰 색인) 또는 페이지를 다음과 같이 분할하십시오.

[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]

여기 에서 관련 페이지에 현재 공간이 있으므로 추가 13하고 17분할하지 않습니다.

[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]

그러나 03을 추가하면 :

[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]

보시다시피, 삽입 작업 후에는 현재 총 20 행에 해당하는 5 개의 데이터 페이지가 할당되어 있지만 14 개의 행만 있습니다 (공간의 30 % 낭비).

기본 옵션으로 재구성하면 (아래의 "채우기 팩터"에 대한 참조) 결과는 다음과 같습니다.

[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]

이 간단한 예에서 한 페이지를 저장합니다. 삭제가 인덱스 순서를 벗어난 삽입과 비슷한 효과를 갖는 방법을 쉽게 알 수 있습니다.

완화

인덱스 순서와 관련하여 데이터가 상당히 임의의 순서로 나타날 것으로 예상 FILLFACTOR되는 경우 인덱스를 만들거나 다시 작성할 때이 옵션을 사용하여 SQL Server가 나중에 채우기 위해 간격을 인위적으로 남겨 두도록함으로써 장기적으로 페이지 분할을 줄이지 만 처음에는 더 많은 공간을 차지합니다. 물론이 값을 잘못 설정하면 상황을 개선하기보다는 상황을 훨씬 악화시킬 수 있으므로주의해서 다루십시오.

특히 클러스터형 인덱스에서 페이지 분할은 삽입 / 업데이트에 성능에 영향을 FILLFACTOR줄 수 있으므로 많은 쓰기 작업을 보는 데이터베이스의 공간 사용 문제 대신 읽기가 쓰기보다 중요한 경우가 종종 있습니다. 여러 순서로, 효과적으로 임의의 내용을 가진 열에 인덱스가있는 경우를 제외하고 채우기 비율을 100 %로 두는 것이 좋습니다.

다른 큰 이름의 DB도 이와 같은 수준의 제어가 필요한 경우 비슷한 옵션이 있다고 가정합니다.

최신 정보

ALTER INDEX위의 입력을 시작한 후 질문에 추가 된 문장에 관해서는 : 옵션이 인덱스가 처음 빌드 될 때와 같거나 마지막으로 다시 빌드 될 때와 같지만 압축 옵션이 추가 된 경우 압축 옵션이 매우 중요하다고 가정합니다 주위에 시간. 또한이 문장에서 fillfactor는 100 %가 아닌 85 %로 설정되므로 각 리프 페이지는 재구성 후 즉시 15 % 비어 있습니다.


2
+1 페이지 채우기 비율이 100 % 미만인 경우 (예 : 페이지 채우기 비율이 50 % 인 경우) 새로 재 구축 된 클러스터형 인덱스 ( 테이블 )는 100 % 채우기 비율로 재 구축 된 것보다 두 배 더 큽니다.
Max Vernon

6

색인을 재 구축하면 문자 그대로 모든 데이터를 새 페이지에 배치합니다. 내가 의심 한 것은 다시 작성하기 전에 많은 데이터를 제거했습니다 (예 : 열 제거, 가변 너비 열을 적은 데이터로 업데이트하거나 고정 너비 열 크기 변경 또는 많은 행 삭제). 이러한 작업 중 하나가 페이지에 많은 빈 공간을 남길 수 있으며, 이는 다시 빌드 할 때까지 회수되지 않습니다. 의 "데이터"열 sp_spaceused은 실제 데이터를 측정하는 것이 아니라 데이터를 저장하는 데 사용 된 8K 페이지 수입니다. 재 구축으로 인해 해당 페이지가 더 가득 차서 동일한 양의 데이터가 더 적은 수의 페이지에 적합합니다.


5

그만큼 sp_spaceused저장 프로 시저가 데이터베이스에있는 행의 총 culmulative 크기를 검사하지 않습니다. 데이터에 할당 된 익스텐트의 누적 크기로 해당 데이터를 보유하기 위해 할당 된 공간의 크기를보고합니다.

삭제 된 많은 행에서와 같이 사용 가능한 여유 공간이 많은 경우 클러스터형 인덱스를 다시 작성하면 성능상의 이유로 페이지의 공간이 축소되고 더 효율적으로 (즉, 더 작게) 확장됩니다.

따라서 데이터 를 버리지 않아야했지만 재구성 프로세스로 인해 데이터 페이지에 포함 된 여유 공간이 다시 사용 가능해졌습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.