ALTER INDEX ALL REBUILD는 각 인덱스를 개별적으로 재 구축하는 것보다 간단한 복구 모델로 더 많은 트랜잭션 로그 공간을 사용합니까?


18

트랜잭션 로그에 공간이 부족하여 SQL Server 2012에서 "ALTER INDEX ALL REBUILD"작업이 실패했습니다. 인덱스는 재구성되거나 재구성되지 않았으므로 거의 모든 인덱스에서 조각화가 80 % 이상입니다.

DB는 단순 복구 모델을 사용합니다. "ALL"형식의 명령으로 수행 된 각 인덱스 작업에 이어 다음 인덱스 재구성 전에 트랜잭션 로그 데이터가 플러시 될 것이라고 가정했습니다. 이것이 실제로 작동하는 방식입니까, 아니면 인덱스 재 구축이 마치 단일 트랜잭션의 일부인 것처럼 기록됩니까?

다시 말해, 각 재 구축을 개별적으로 수행하는 스크립트를 작성하여 트랜잭션 로그 증가를 줄일 수 있습니까? 고려해야 할 다른 요소가 있습니까?


2
명시 적 데이터를 반대로, 특정 SQL 명령은 DB 엔진에 의해 단일 원자 트랜잭션으로 간주된다고 가정합니다. 이 경우 이론을 상당히 쉽게 테스트 할 수 있습니다. 가장 큰 인덱스를 가져 와서 다시 작성하십시오. 성공하면 로그가 여러 재 구축 정보를 축적하고 있다고 가정하는 것이 합리적입니다. 실패하면 로그 공간을 추가하거나 (어느 쪽이든 문제가 있기 때문에) 다시 작성하는 대신 인덱스를 재구성해야합니다 (t-에 대한 공간을 늘릴 수없는 경우) 로그).
RDFozz

그렇습니다.이 생각을 입력 한 것처럼 나에게 그 생각이 들었습니다 (고무 오리 효과). 나는 확인을 얻고 같은 생각을하는 다른 사람들에게 맡기는 것이 가장 좋을 것이라고 생각했습니다. 이 환경을 실험하고 싶지 않으므로 아마도 로그에 공간을 추가하게 될 것입니다.
Google 실패

답변:


16

"ALL"형식의 명령으로 수행 된 각 인덱스 작업에 이어 다음 인덱스 재구성 전에 트랜잭션 로그 데이터가 플러시 될 것이라고 가정했습니다. 이것이 실제로 작동하는 방식입니까, 아니면 인덱스 재 구축이 마치 단일 트랜잭션의 일부인 것처럼 기록됩니까?

1) 로그 플러시 : SIMPLE 복구 모델은 모든 트랜잭션 후가 아니라 체크 포인트에서 로그를 지우지 않습니다. ( 자세한 정보는 링크 )

2a) REBUILD ALL : 예, REBUILD ALL은 단일 트랜잭션으로 작동합니다. 인덱스 재 구축에는 자체 트랜잭션이 있지만 전체 작업이 끝날 때까지 완전히 커밋되지는 않습니다. 따라서 개별 인덱스를 다시 작성하고 CHECKPOINT 명령을 실행하여 로그 파일 증가를 제한 할 수 있습니다.

2b) 증명! 여기, 데모 스크립트가 있습니다. (2016 dev에 내장 됨) 먼저 테이블과 인덱스를 사용하여 테스트 DB를 설정하십시오.

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')

이제 REBUILD ALL과 개별적으로 재 구축 간의 로그 활동을 비교할 수 있습니다.

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

REBUILD ALL이 끝날 때까지 첫 번째 공개 트랜잭션 (트랜잭션 ID 0000 : 000002fa)이 커밋되지 않지만 인덱스 별 재 구축의 경우 연속적으로 커밋됩니다.


와우, 정말 자세한 답변 감사합니다! 그것은 후드에서 무슨 일이 일어나고 있는지 알 수있는 좋은 방법입니다.
Google Fail

잘 설명했다.
라마 칸트 다디 치

4

그대로, 이것은 단일 거래입니다.


6
DBA.SE에 오신 것을 환영합니다! 일반적으로 최선의 답변은 단순한 주장이 아니라 문서 나 기사의 정보 또는 명시된 답변을 입증하는 개인적인 경험으로 뒷받침됩니다. 그런 종류의 뒷받침을 제공하기 위해 답을 넓힐 수 있습니까?
RDFozz

2
@RDFozz 공정한 의견이지만 Pedro의 프로필을 보셨습니까 ? 소스 코드에 대한 액세스는 개인적인 경험이나 문서보다 권위있는 것으로 간주 될 수 있습니다. :-)
Aaron Bertrand

3
@AaronBertrand-나는 고백하지 않았다. 확실히 SQL Server 팀의 일원이되는 것이 실제로 자격이 있다고 생각합니다. 여전히 대답에서 참조 할 가치가 있습니다. 어쨌든 +1.
RDFozz

3

오프라인 재 구축에 대한 질문은 간단합니다 . 물론 단일 거래입니다. 작업이 각 인덱스를 자체 트랜잭션으로 분할 할 경우 발생하는 혼란을 상상해보십시오.커밋 할 때 잠금 해제 한 다음 다시 획득해야 . 임계 테이블 SCH-M 잠금이 해제되는 동안 인덱스가 삭제되고 새 인덱스가 작성 될 수 있습니다. 명령문은 이러한 경우를 어떻게 처리합니까? 말할 것도없이 두 테이블 사이에서 테이블 이 삭제되거나 다시 생성 될 수도 있습니다! 테이블이 삭제되고 동일한 객체 ID 로 다른 테이블이 생성되는 경우를 포함합니다 (예, 발생할 수 있음) ...

인덱스 재 구축이 온라인 인 경우 어떻게되는지 말하기 위해 질문을 보강하면 어떻게됩니까? 재 되나요? 단일 거래입니까 아니면 많은 거래입니까? 실제로 몇 가지 내부 트랜잭션이 관련 되어 있기 때문에 대답은 복잡 합니다 . 그러나 중요한 점은 전체 작업 (ALTER 문)에 걸쳐있는 전체 아키 징 트랜잭션이 있으며 이로 인해 로그가 고정됩니다 (잘라낼 수 없음). 따라서 1.6x 데이터를 허용하도록 작업을 계획해야합니다 전체 복구 모드의 경우 크기, BULK_LOGGED / SIMPLE 모드의 경우 0.2x 데이터 크기. 자세한 내용은 연결된 용지를 참조하십시오.

오프라인 빌드가 온라인 모드와 동일한 내부 트랜잭션을 사용하지 않고 작업을 분할하지 않는 이유는 무엇입니까? 개별 인덱스 작업 (예 : 테이블 '스키마 안정성')간에 변경 / 삭제되는 테이블에 대해 언급 한 문제는 여전히 전체 명령문 기간 동안 테이블에 SCH-S를 보유하는 포괄 트랜잭션이 필요합니다. 이 트랜잭션은 복구 중에도 SCH-S를 보유해야하므로 로그되어야하며, 따라서 명령문 전체에서 로그를 고정하고 잘림을 방지하는 BEGIN XACT 로그 레코드가 있습니다. 이 특정 문제가 SQL 2016-2017 시간대 (SQL Azure 로그 크기 문제로 인해)에서 해결되고 있음을 알고 있지만 진행 상황이 확실하지 않습니다 . 미리보기 상태 인 것 같습니다.재개 가능한 온라인 인덱스 다시 작성은 SQL Server 2017 CTP 2.0에 대한 공개 미리보기입니다 .


0

예, 매우 큰 테이블에서 이와 동일한 문제가 발생했습니다. ALTER INDEX ALL을 발행 할 때마다 트랜잭션 로그가 많이 커지지 만 ALTER INDEX를 개별적으로 발행하면 로그 공간 사용량이 줄어 듭니다.


0

온라인 색인 작성에 전체 복구 모드에서 색인 크기의 1.6 배가 필요하다는 Remus의 초기 응답은 올바르지 않습니다. FULL에서 온라인으로 인덱스를 다시 작성하는 데 필요한 트랜잭션 로깅 공간의 비율이 훨씬 높을 수 있으며, 특히 트랜잭션 로깅이 압축되지 않아 다시 작성중인 인덱스가 압축 된 경우 인덱스 크기가 여러 번 관찰되었습니다. 이것만으로도 FULL 하에서 온라인 재 구축 중 트랜잭션 로깅이 인덱스 크기의 몇 배가 될 수 있음을 분명히해야합니다. Microsoft에서 완전히 문서화하지 않았지만 행당 60 바이트로 추정되는 tlog 레코드 오버 헤드에 추가하십시오. 전체 복구에서 온라인 인덱스를 다시 작성하는 동안 비례 로깅 크기는 특히 다시 작성하는 인덱스 크기의 몇 배가 될 수 있습니다. 지수는 압축된다


-1

Rdfozz는 현재 스토리지를 기반으로 가장 큰 인덱스를 다시 작성할 수 있는지 여부를 결정하는 가장 좋은 방법입니다. dm_exec_requests작업이 진행 되는 동안 (또는 SQL 프로필러) 실행하여 모든 인덱스가 다시 작성되는지 확인하십시오. 복구 모델을 대량 로그로 변경하는 것도 고려할 수 있습니다. 이것이 내가하는 일이며 여전히 창에 트랜잭션 로그 백업이 있습니다. 아래 기사 https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx 참조


2
OP는 DB가 이미 SIMPLE 복구 모델을 사용하고 있다고 언급했습니다. 이것은 트랜잭션이 완료 될 정도로 트랜잭션을 로그에 오래 유지합니다. 대량 로그로 전환하면 개선되지 않습니다.
RDFozz

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