다음은 Microsoft Docs 의 단락입니다 .
DML 작업의 일부로 힙에 할당 된 새 페이지는 힙이 다시 작성 될 때까지 PAGE 압축을 사용하지 않습니다. 압축을 제거했다가 다시 적용하거나 클러스터형 인덱스를 만들고 제거하여 힙을 다시 작성하십시오.
이것이 왜 그런지 알 수 없습니다. 지정된 압축 설정을 가진 힙이 있으면 왜 테이블에 속하는 페이지에 적용되지 않습니까?
감사
다음은 Microsoft Docs 의 단락입니다 .
DML 작업의 일부로 힙에 할당 된 새 페이지는 힙이 다시 작성 될 때까지 PAGE 압축을 사용하지 않습니다. 압축을 제거했다가 다시 적용하거나 클러스터형 인덱스를 만들고 제거하여 힙을 다시 작성하십시오.
이것이 왜 그런지 알 수 없습니다. 지정된 압축 설정을 가진 힙이 있으면 왜 테이블에 속하는 페이지에 적용되지 않습니까?
감사
답변:
차이점을 담당하는 특정 내부 메커니즘을 모르지만 힙은 클러스터형 인덱스 (및 비 클러스터형 인덱스)와 약간 다르게 (내부적으로) 관리된다고 말할 수 있습니다.
하나 이상의 데이터 페이지가 비어 있도록 (할당 된 행 없음) 힙에서 행을 삭제해도 해당 공간을 확보 할 필요는 없습니다. 테이블에서 클러스터형 인덱스를 만든 다음 삭제하거나 ALTER TABLE [TableName] REBUILD;
SQL Server 2014에서와 같이 호출 해야 할 수도 있습니다. 자세한 내용과 옵션 은 DELETE에 대한 Microsoft 문서 페이지를 참조하십시오 .
개별 행 삽입 (예 : 세트 기반 아님)INSERT
아님)을 힙에 삽입해도 클러스터 된 인덱스에서와 같이 데이터 페이지가 완전히 채워지지 않습니다. 클러스터 된 인덱스는 행 (데이터 및 행 오버 헤드)을위한 공간과 슬롯 배열의 2 바이트 오버 헤드가있는 한 행에 적합합니다. 그러나 힙의 데이터 페이지는 페이지에 남아있는 바이트 수를 사용하지 않고 대신 페이지가 얼마나 찼는 지에 대한 매우 일반적인 표시기를 사용하며보고 된 레벨이 많지 않습니다. 레벨은 0 %, 20 %, 50 %, 80 % 및 100 % 꽉 찬 줄을 따라 있습니다. 그리고 여전히 다른 행을위한 공간이있는 동안 100 %로 전환됩니다 (실제로 같은 수의 행이 세트 기반 조작에 삽입 된 경우 가능한 한 페이지를 채웠습니다). 물론, 마찬가지로DELETE
힙을 다시 빌드하면 데이터 페이지에 맞는만큼의 행이 압축됩니다.
이제 페이지 압축 구현에 대한 Microsoft 문서 페이지의 "페이지 압축이 발생할 때"섹션에서 가져온 다음 정보를 고려하십시오 .
... 첫 번째 데이터 페이지에 데이터가 추가되면 데이터가 행 압축됩니다. ... 페이지가 가득 차면 추가 할 다음 행이 페이지 압축 조작을 시작합니다. 전체 페이지가 검토됩니다. ...
따라서 데이터 페이지를 작성하기 전에 ALTER TABLE REBUILD, 클러스터형 인덱스의 CREATE / DROP 또는 데이터 압축 설정의 변경 (모두 힙을 다시 작성)이 필요한 다른 힙 동작과 완전히 일치하는 것처럼 보입니다. 최적으로. 힙이 "전체 페이지"를 완전히 인식하지 못하고 (힙이 재 빌드 될 때까지) 페이지가 완전히 가득 찬시기를 모른다면, 페이지 압축 조작을 시작할시기를 알 수 없습니다 (업데이트 및 단일 처리시) 행 삽입).
자동 적용 페이지 압축에서 일부 힙이 더 제한되는 또 다른 기술 (다른 방법으로 가능하더라도) 압축을 적용하려면 해당 힙 (있는 경우)에 대한 모든 비 클러스터형 인덱스를 다시 작성해야합니다. "데이터 압축"에 대한 링크 된 페이지에도 다음과 같이 명시되어 있습니다.
힙의 압축 설정을 변경하면 힙의 새 행 위치에 대한 포인터를 갖도록 테이블의 모든 비 클러스터형 인덱스를 다시 작성해야합니다.
참조되는 "포인터"는 행 ID (RID)이며 FileID, PageID 및 페이지의 슬롯 / 위치의 조합입니다. 이러한 RID는 비 클러스터형 인덱스로 복사됩니다. 정확한 물리적 위치이기 때문에 때때로 클러스터형 인덱스 키를 사용하여 b- 트리를 탐색하는 것보다 빠른 조회가 가능합니다. 그러나 물리적 위치의 한 가지 단점은 위치가 변경 될 수 있다는 것입니다. 이것이 바로 여기서 문제입니다. 그러나 클러스터 된 인덱스는 키 값이 클러스터 된 인덱스에 대한 포인터로 비 클러스터형 인덱스에 복사되므로이 문제가 발생하지 않습니다. 물리적 위치가 변경 되더라도 키 값은 동일하게 유지됩니다.
참조 :
힙에 대한 Microsoft 문서 페이지의 "힙 관리"섹션 (클러스터형 인덱스가없는 테이블) :
낭비되는 공간을 확보하기 위해 힙을 재 구축하려면 힙에 클러스터형 인덱스를 생성 한 다음 해당 클러스터형 인덱스를 삭제하십시오.
데이터 압축에 대한 Microsoft 문서 페이지의 "행 및 페이지 압축 사용시 고려 사항"섹션 :
페이지 레벨 압축을 위해 힙이 구성된 경우 페이지는 다음과 같은 방식으로 만 페이지 레벨 압축을받습니다.
- 대량 최적화를 사용하여 데이터를 대량으로 가져옵니다.
- INSERT INTO ... WITH (TABLOCK) 구문을 사용하여 데이터를 삽입했으며 테이블에 비 클러스터형 인덱스가 없습니다.
- PAGE 압축 옵션으로 ALTER TABLE ... REBUILD 문을 실행하여 테이블이 재 빌드됩니다.
그리고 그 진술은 질문에 인용되었습니다.
SQL Server의 모든 메커니즘이 꼭 필요한 것은 아닙니다.
Paul Randal은 문제 관리에 대한 강력한 권장 사항을 제공했습니다.
http://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2930-fixing-heap-fragmentation/