SQL Server : 힙 + 클러스터되지 않은 인덱스로 구성된 테이블의 DELETE가 느립니다.

3187 단어 SQLServerDB

배경


delete from Table where Column1 = 'xxxx' 

이 쿼리로 인해 몇 분 동안 차단이 계속 발생했기 때문에 원인을 조사했습니다.
언제나 1분 이내에 완료하는 쿼리입니다만, 가끔 원인 불명으로 10분 이상 실행되는 일이 있어, 그 타이밍에 다른 쿼리를 블록 하고 있는 것 같습니다.

테이블 구성



힙 + Column1 키의 비 클러스터형 인덱스
레코드 수: 약 20만 행

조사 방법



여기 의 방법으로 1분마다 DMV의 덤프를 테이블에 보존해 가, 이벤트가 재현했을 때의 실행 상태의 천이를 확인했습니다.



1분마다의 스냅샷의 정보이므로, 사이의 상태 천이는 정확하게는 모릅니다만, 모두 status=runnable/last_wait_type=PAGELATCH_EX이기 때문에, 10분간 계속 이 상태였을 것으로 예상됩니다.

또, 레코드수는 20만행 정도 밖에 없고, 인덱스의 용량도 20MB 정도 밖에 없습니다만, logical_reads(논리 읽기)의 사이즈가 매우 크고, 최종적으로 10GB 이상 읽고 있다고 하는 특징도 보여졌습니다 .

그 타이밍만 레코드수가 매우 많았던 것은? 라는 생각도 했기 때문에, 레코드수의 추이에 대해서도 확인했습니다만, 큰 변화는 보이지 않았습니다.


테이블 사이즈는 항상 약 20만 레코드 정도로 14-20MB 정도임에도 불구하고, 10GB 오버의 논리 읽기가 발생하고 있다고 하는 것은, 실행 플랜이 이상해지고 슬로우 다운하고 있을 가능성이 생각할 수 있습니다.

query_plan_hash는 실행 계획이 동일하면 재생성되어도 동일합니다. 그 때문에, 빠르고 늦은 때와 query_plan_hash에 차이가 있는지를 보는 것으로, 「실행 플랜이 이상해졌는지」에 대해서는 어느 정도 정확도를 높일 수 있다고 생각해, 확인해 보았습니다.
select * from
dm_exec_requests_dump with(nolock)
where command_text like '%delete from Table where Column1 = %'
order by collect_date


hash 값은 빠르거나 느릴 때 같았습니다. 그렇다고 하는 것은, 실행 플랜이 바뀐 것은 아닐 것 같습니다.

여기서 조사는 막혔습니다.
어떠한 요인으로, 빠르고 늦은 때가 있는 것 같습니다만, 그 요인에는 도착하지 못했습니다.

힙 vs 클러스터형 인덱스



이번 테이블은 힙이었습니다만, 클러스터화 인덱스로 구성된 테이블 쪽이 프로덕션 환경에서 압도적으로 많아, 이 양자의 DELETE시의 논리 읽기수에 얼마나 차이가 있는지 조사해 보았습니다.

그 결과, 「힙 + 비클러스터화 인덱스」테이블의 DELETE는, 「클러스터화 인덱스」테이블의 DELETE보다, 논리 읽기가 약 30배 정도 많다고 하는 결과가 되었습니다.

일반적인 경향으로, 힙으로 구성된 테이블 쪽이 동일한 레코드 수라도 DELETE시의 논리 읽기 페이지 수는 상당히 커지는 것 같습니다. 그러나 그렇다고 해서 20만 레코드 테이블의 DELETE가 차단되지 않고 10분 이상 걸리는 이유는 아닙니다.

실시한 대응



"힙 특유의 뭔가"때문에 DELETE에 평소보다 상당히 시간이 걸릴 수 있다고 생각하고, 최종적인 대응으로서는 클러스터화 인덱스를 작성했습니다.

이로 인해 현재 급격한 DELETE 쿼리가 느려지지 않습니다.

똑같이 힙을 사용한 테이블에서 원인 불명의 슬로우 다운에 고민되고 있는 분은 클러스터화 인덱스화하면 해소될 가능성이 있습니다.

좋은 웹페이지 즐겨찾기