クラスタ化インデックスを使用してSQL Serverテーブルからデータを削除するときに、Bツリーは再調整されますか?


10

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

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

削除操作によってインデックスが再調整されるため、再構築プロセス中にテーブルの任意の行でキーロックが発生する可能性があると思います。

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


いい質問だと思います。はい、レコードを削除すると、インデックスが再構築されます。再構築中、テーブルはロックされ、他のユーザーはそのテーブルにアクセスできなくなります。stackoverflow.com/questions/6309614/...
KumarHarsh

4
いいえ、クラスター化インデックスの行を削除しても、インデックスは再構築されません。データの削除に使用したクエリも投稿できますか。Uロックは、クエリが削除されるデータを見つけようとするときに発生し、最後に行を排他的にロックして削除します。
シャンキー

2
削除が発生すると、「ホール」が作成されます。または、クラスター化インデックスからデータが削除されたときにスペースと言うことができます。これはページ密度を低くする可能性があり、断片化と見なすことができます。CIで挿入が発生すると、右側のレコードがいっぱいになるため、スペースがいっぱいになることはありません。ただし、SQL Serverがこのスペースを自動的に削除するわけではありません。このスペースを満たすには、インデックスを再構築するか、再編成する必要があります。そのようなリバランスはあり
ません

1
@jayesh私は、ツリー内のノードの順序がリバランスとどのように関係しているのかわかりません。Bツリーは(挿入または削除のため)不均衡になる可能性があります。これらの場合、ノードの順序は変わりません。それは単に不均衡な木です。
ypercubeᵀᴹ

1
@jayeshあなたが使用している用語があなたと私たちの両方を混乱させていると思うので、MSSQLドキュメントのいくつかを読むことはあなたに利益をもたらすと思います。
LowlyDBA 2018

回答:


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.