web-dev-qa-db-ja.com

クラスタ化インデックスを持つSQL Serverテーブルからのデータの削除中に、Bツリーは再調整されますか?

SQL Serverデータベースに、主キーのクラスター化インデックスを持つテーブルがあります。テーブルには100万行あります。テーブルから10K行を削除した場合、削除操作の実行中にインデックスが再構築されますか?

削除操作はストアドプロシージャの一部です。一度に複数のクライアントがストアドプロシージャを実行できますが、個々の実行ごとに独自の行のセット(主キーによって一意に識別される)が削除されます。複数のクライアントがプロシージャを実行すると、キーロック(タイプU)がブロックされます。ブロッカーロックは同じテーブルの行に属し、同時に実行されているトランザクションの一部ではありません。各実行はそれ自体の行のセットを削除しようとしているため、ブロックはありません。ロックのエスカレーションはオフになっているため、発生していません。

削除操作はインデックスの再バランスを引き起こしているに違いないので、再構築プロセス中にテーブルの任意の行でキーロックを取得する可能性があります。

これについてのご意見をいただければ幸いです。

10
jayesh

タイトルの質問に答えると、削除中に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ツリーを生成できることを示しています。

3
Forrest