클러스터 된 인덱스가있는 SQL Server 테이블에서 데이터를 삭제하는 동안 B-Tree의 균형이 재조정됩니까?


10

기본 키에 클러스터 된 인덱스가있는 SQL Server 데이터베이스에 테이블이 있습니다. 테이블에는 백만 개의 행이 있습니다. 테이블에서 10K 행을 삭제하면 삭제 작업 중에 인덱스가 재구성됩니까?

삭제 작업은 저장 프로 시저의 일부입니다. 한 번에 둘 이상의 클라이언트가 저장 프로 시저를 실행할 수 있지만 각 개별 실행은 고유 한 행 집합 (기본 키로 고유하게 식별 됨)을 삭제합니다. 여러 클라이언트가 프로 시저를 실행할 때 키 잠금 (유형 U)이 차단됩니다. 블로커 잠금은 동일한 테이블의 행에 속하며 동시에 실행중인 트랜잭션의 일부가 아닙니다. 각 실행이 자체 행 집합을 삭제하려고 시도 할 때 차단이 없어야합니다. 잠금 에스컬레이션이 해제되어 있지 않습니다.

삭제 작업으로 인해 인덱스의 균형이 조정되어야하므로 재구성 프로세스 중에 테이블의 모든 행에서 키 잠금이 필요할 수 있습니다.

나는 이것에 대한 의견을 정말로 감사하겠습니다.


좋은 질문과 좋은 추측. 예, record를 삭제하면 인덱스가 다시 작성됩니다. 재 구축 프로세스 테이블이 잠기면 다른 사용자는 해당 테이블에 액세스 할 수 없습니다. stackoverflow.com/questions/6309614/…
KumarHarsh

4
아니요, 클러스터형 인덱스에서 행을 삭제해도 인덱스가 다시 작성되지 않습니다. 데이터를 삭제하는 데 사용 된 쿼리를 게시 할 수도 있습니다. 쿼리가 삭제 될 데이터를 찾으려고하면 마지막으로 행을 잠 가서 삭제합니다.
Shanky

2
삭제가 발생하면 "구멍"이 생성되거나 데이터가 클러스터형 인덱스에서 제거 될 때 공간을 말할 수 있습니다. 이로 인해 페이지 밀도가 낮아지고 조각화로 간주 될 수 있습니다. CI에서 삽입이 발생하면 오른쪽의 레코드가 채워지고 이로 인해 공간이 채워질 수 없습니다. 그러나 SQL Server는이 공간을 자동으로 제거하지 않습니다. 이 공간을 채우려면 인덱스를 다시 작성하거나 재구성해야합니다. 이와 같은 재조정은 없습니다
Shanky

1
@ jayesh 나는 트리의 노드 순서가 재조정과 어떻게 관련이 있는지 알지 못합니다. B- 트리의 균형이 맞지 않을 수 있습니다 (삽입 또는 삭제로 인해). 이 경우 노드 순서는 변경되지 않습니다. 균형이 맞지 않는 나무 일뿐입니다.
ypercubeᵀᴹ

1
@ jayesh 나는 당신이 사용하는 용어가 당신과 우리 모두를 혼란스럽게 생각하기 때문에 일부 MSSQL 문서를 읽는 것이 도움이 될 것이라고 생각합니다.
LowlyDBA

답변:


3

삭제 중에 B- 트리가 균형을 재조정했는지 여부에 대한 제목의 질문에 대답하기 위해 최소한 다음과 같은 최소한의 테스트 사례에서는 대답이 아니오로 나타납니다.

다음 데모는 테스트 환경에 가장 적합한 명령을 실행합니다.

--create table and fill it
DROP TABLE IF EXISTS bunchesofints
CREATE TABLE bunchesofints (
thisisanint INT PRIMARY KEY CLUSTERED,
junkrow CHAR(1000) NOT NULL
)

INSERT dbo.bunchesofints
SELECT TOP 5000
ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS thisisanint,
REPLICATE('a',1000) AS junkrow
FROM sys.all_objects a1
CROSS JOIN sys.all_objects a2


--with this query we can see all the non-leaf pages of the b-tree, plus the IAM
SELECT allocated_page_page_id, page_type_desc, page_level, is_allocated, next_page_page_id, previous_page_page_id
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.bunchesofints'),NULL,NULL,'DETAILED')
WHERE page_type != 1
GO

--Ok, let's delete most of the rows
;WITH CTE AS (
    SELECT TOP (4500) *
    FROM dbo.bunchesofints
    ORDER BY thisisanint DESC
)

DELETE 
FROM CTE
GO

--Hmm, still have 3 non-leaf index pages
SELECT allocated_page_page_id, page_type_desc, page_level, is_allocated, next_page_page_id, previous_page_page_id
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.bunchesofints'),NULL,NULL,'DETAILED')
WHERE page_type != 1



--So, where are the rows?
--please note the assumption that your test database has a single file.
DECLARE @firstindexpage INT, @lastindexpage INT, @db INT = DB_ID()
SELECT @firstindexpage = MIN(previous_page_page_id), @lastindexpage = MAX(next_page_page_id)
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.bunchesofints'),NULL,NULL,'DETAILED')
WHERE page_type = 2 AND page_level = 1

DBCC PAGE(@db,1,@firstindexpage,3) WITH TABLERESULTS
DBCC PAGE(@db,1,@lastindexpage,3) WITH TABLERESULTS

이 데모는 삭제로 인해 거의 모든 데이터가 한쪽에있는 매우 불균형 한 b- 트리를 생성 할 수 있음을 보여줍니다.


명확하고 간결한 설명 및 데모 코드를 제공해 주셔서 감사합니다. 나는 이것을 시도 할 것이다. 이 답변을 수락하겠습니다. 분리 된 행 집합에서 삭제로 인해 클러스터 된 인덱스가있는 테이블에서 차단이 발생하는 이유를 여전히 알아 내려고 노력 중입니다.
jayesh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.