삭제 대 절단


35

DELETETRUNCATE명령 의 차이점에 대해 더 잘 이해하려고 합니다. 내부에 대한 나의 이해는 다음과 같은 내용을 따릅니다.

DELETE-> 데이터베이스 엔진은 관련 데이터 페이지 및 행이 입력 된 모든 인덱스 페이지에서 행을 찾아서 제거합니다. 따라서 인덱스가 많을수록 삭제 시간이 오래 걸립니다.

TRUNCATE -> 단순히 테이블의 모든 데이터 페이지를 제거하여 테이블의 내용을 삭제하는 데 더 효율적인 옵션입니다.

위의 내용이 정확하다고 가정합니다 (그렇지 않은 경우 수정 해주세요).

  1. 각기 다른 복구 모드가 각 명령문에 어떤 영향을 줍니까? 전혀 효과가 없다면
  2. 삭제할 때 모든 인덱스가 스캔됩니까? 아니면 행이있는 인덱스 만 스캔됩니까? 모든 색인이 스캔되었다고 가정합니다 (검색하지 않습니까?)
  3. 명령은 어떻게 복제됩니까? 각 가입자에서 SQL 명령이 전송 및 처리됩니까? 아니면 MSSQL이 그보다 조금 더 지능적입니까?

2
바로 앞에 -ing 유틸리티에 대한 이 질문 에 대한 답변 DELETE과 관련 정보 가 있습니다. 또한 이 답변에 설명 된 기술을 사용하여 두 명령의 효과를 연구하기 위해 로그를 직접 살펴볼 수도 있습니다 . TRUNCATETRUNCATEDROP
Nick Chammas

1
이 답변 은 DELETE 및 TRUNCATE 작업의 내부를 보여줍니다. 또한 질문은 TRUNCATE가 더 잘 작동하는 특정 상황을 보여줍니다.
孔夫子

5
@idstam TRUNCATE을 롤백 할 수 있습니다. 닉은 그의 대답에 있음을 커버 질문 그가 연결 .
Mark Storey-Smith

잘라내기에는 "테이블 변경"권한이 필요합니다 (잘라내 기가 삭제 대신 플러그 인됨을 의미합니다).
crokusek

답변:


58

DELETE-> 데이터베이스 엔진은 관련 데이터 페이지 및 행이 입력 된 모든 인덱스 페이지에서 행을 찾아서 제거합니다. 따라서 인덱스가 많을수록 삭제 시간이 오래 걸립니다.

네, 여기에는 두 가지 옵션이 있습니다. 기본 테이블 삭제를 수행하는 동일한 연산자로 비 클러스터형 인덱스에서 행을 행별로 삭제할 수 있습니다. 이것은 좁은 (또는 행별) 업데이트 계획으로 알려져 있습니다.

행당 삭제

또는 비 클러스터형 인덱스 삭제는 비 클러스터형 인덱스 당 하나씩 별도의 연산자로 수행 될 수 있습니다. 이 경우 (와이드 또는 인덱스 별 업데이트 계획이라고 함) 전체 조치 세트는 작업 테이블 (열성 스풀)에 저장되기 전에 인덱스 당 한 번 재생되기도합니다. 액세스 패턴.

인덱스 당 삭제

TRUNCATE->는 단순히 테이블의 모든 데이터 페이지를 제거하여 테이블의 내용을 삭제하는 데 더 효율적인 옵션입니다.

예. TRUNCATE TABLE여러 가지 이유로 더 효율적입니다.

  1. 잠금 장치가 더 필요할 수 있습니다. 잘림은 일반적으로 테이블 레벨에서 단일 스키마 수정 잠금 (및 할당 해제 된 각 범위의 독점 잠금 ) 만 필요합니다. 삭제는 할당 해제 된 모든 페이지의 독점 잠금뿐만 아니라 더 낮은 (행 또는 페이지) 단위로 잠금을 획득 할 수 있습니다 .
  2. 잘림만으로 모든 페이지가 힙 테이블에서 할당 해제됩니다. 배타적 테이블 잠금 힌트가 지정된 경우에도 (예 : 데이터베이스에 행 버전 지정 격리 수준을 사용하는 경우) 삭제하면 힙에 빈 페이지가 남을 수 있습니다.
  3. 잘림은 사용중인 복구 모델에 관계없이 항상 최소로 기록 됩니다. 페이지 할당 해제 작업 만 트랜잭션 로그에 기록됩니다.
  4. 객체의 크기가 128 개 이상인 경우 잘림은 지연 드롭을 사용할 수 있습니다 . 지연된 삭제는 실제 할당 해제 작업이 백그라운드 서버 스레드에 의해 비동기 적으로 수행됨을 의미합니다.

각기 다른 복구 모드가 각 명령문에 어떤 영향을 줍니까? 전혀 효과가 있습니까?

삭제는 항상 완전히 기록됩니다 (삭제 된 모든 행은 트랜잭션 로그에 기록됨). 복구 모델이 이외의 경우 로그 레코드의 내용에는 약간의 차이가 FULL있지만 여전히 기술적으로 전체 로깅입니다.

삭제할 때 모든 인덱스가 스캔됩니까? 아니면 행이있는 인덱스 만 스캔됩니까? 모든 색인이 스캔되었다고 가정합니다 (검색하지 않습니까?)

인덱스에서 행을 삭제하면 (앞에 표시된 좁거나 넓은 업데이트 계획 사용) 항상 키 (검색)를 통해 액세스 할 수 있습니다. 삭제 된 각 행에 대한 전체 색인을 스캔하는 것은 끔찍하게 비효율적입니다. 앞에서 설명한 인덱스 별 업데이트 계획을 다시 살펴 보겠습니다.

넓은 계획 2

실행 계획은 수요 중심 파이프 라인입니다. 부모 연산자 (왼쪽)는 자식 연산자가 한 번에 행을 요청하여 작업을 수행하도록합니다. 정렬 연산자는 차단하고 있지만 (첫 번째 정렬 된 행을 생성하기 전에 전체 입력을 사용해야 함) 여전히 첫 번째 행을 요청하는 부모 (인덱스 삭제)에 의해 구동됩니다. 인덱스 삭제 완료된 정렬 에서 한 번에 한 행을 가져 와서 각 행의 대상 비 클러스터형 인덱스를 업데이트합니다.

광범위한 업데이트 계획에서는 기본 테이블 업데이트 연산자에 의해 행 스트림에 열이 추가되는 경우가 종종 있습니다. 이 경우 클러스터형 인덱스 삭제는 비 클러스터형 인덱스 키 열을 스트림에 추가합니다. 이 데이터는 스토리지 엔진에서 클러스터되지 않은 인덱스에서 제거 할 행을 찾는 데 필요합니다.

출력 목록 세부 사항

명령은 어떻게 복제됩니까? 각 가입자에서 SQL 명령이 전송 및 처리됩니까? 아니면 SQL Server가 그보다 조금 더 지능적입니까?

트랜잭션 또는 병합 복제를 사용하여 게시 된 테이블에서는 잘림이 허용되지 않습니다 . 삭제 복제 방법은 복제 유형과 구성 방법에 따라 다릅니다. 예를 들어 스냅 샷 복제는 대량 방법을 사용하여 테이블의 특정 시점보기를 복제하기 만합니다. 증분 변경 내용은 추적되거나 적용되지 않습니다. 트랜잭션 복제는 로그 레코드를 읽고 구독자에게 변경 사항을 적용 할 적절한 트랜잭션을 생성하여 작동합니다. 병합 복제는 트리거 및 메타 데이터 테이블을 사용하여 변경 사항을 추적합니다.

관련 읽기 : 데이터를 변경하는 T-SQL 쿼리 최적화

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