Kümelenmiş bir dizinle SQL Server tablosundan veri silinirken B-Tree yeniden dengeleniyor mu?


10

Birincil anahtarda kümelenmiş bir dizin ile bir SQL Server veritabanında bir tablo var. Tabloda 1 milyon satır var. 10K satırı tablodan silersem, silme işlemi yapılırken dizin yeniden yapılandırılır mı?

Silme işlemi, saklı yordamın bir parçasıdır. Bir kerede, birden fazla istemci saklı yordamı yürütebilir, ancak her bir çalıştırma kendi satır kümesini siler (benzersiz olarak birincil anahtarla tanımlanır). Birden fazla istemci yordamı yürüttüğünde Tuş kilidi (U türü) üzerinde engelleme alıyorum. Engelleyici kilidi, aynı tablodaki bir satıra aittir ve eşzamanlı olarak çalışan işlemin herhangi bir parçası değildir. Her çalıştırma kendi satır kümesini silmeye çalıştığından herhangi bir engelleme olmamalıdır. Kilit yükselmesi kapalı olduğu için gerçekleşmiyor.

Şüpheliyim, silme işlemi dizinin yeniden dengelenmesine neden olmalı ve bu nedenle yeniden yapılandırma işlemi sırasında tablonun herhangi bir satırında tuş kilidi alabilir.

Bu konuda herhangi bir görüş gerçekten takdir ediyorum.


Güzel soru ve güzel tahmin. Evet, kaydı sildiğinizde dizin yeniden oluşturulur. Yeniden oluşturma işlemi sırasında tablo kilitlenir ve diğer kullanıcılar bu tabloya erişemez. stackoverflow.com/questions/6309614/…
KumarHarsh

4
HAYIR, kümelenmiş dizindeki satırların silinmesi dizinin yeniden oluşturulmasına neden olmaz. Verileri silmek için kullanılan sorguyu da gönderebilirsiniz. U kilidi, sorgu silinecek verileri bulmaya çalışırken gelir ve son olarak yalnızca silmek için satırları kilitler.
Shanky

2
Silme işlemi gerçekleştiğinde bir "delik" oluşturur veya veriler kümelenmiş dizinden kaldırılırken boşluk diyebilirsiniz. Bu düşük sayfa yoğunluğu oluşturabilir ve parçalanma olarak düşünülebilir. Ekleme CI'de gerçekleştiğinde sağ taraftaki kayıtları dolduracaktır ve bu nedenle boşluk asla doldurulamayabilir. Ancak SQL Server bu alanı otomatik olarak kaldırmayacaktır. Bu alanı doldurmak için dizini yeniden oluşturmanız veya yeniden düzenlemeniz gerekir. Böyle bir dengeleme yok
Shanky

1
@jayesh Bir ağaçtaki düğüm sırasının yeniden dengeleme ile nasıl bir ilgisi olduğunu anlamıyorum. Bir B ağacı dengesiz olabilir (ekler veya siler nedeniyle). Bu durumlarda düğüm sırası değişmez. Sadece dengesiz bir ağaç.
ypercubeᵀᴹ

1
@jayesh Bazı MSSQL belgelerini okumaktan fayda sağlayabileceğinizi düşünüyorum, çünkü kullandığınız terminoloji hem sizi hem de bazılarımızı karıştırıyor.
LowlyDBA

Yanıtlar:


3

Başlıktaki soruyu cevaplamak için, bir silme sırasında B ağacının yeniden dengelenip dengelenmediği, en azından aşağıdaki minimum test durumunda yanıtın hayır olduğu görülüyor.

Aşağıdaki demo, test ortamı için en iyi bırakılan komutları çalıştırır.

--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

Bu demo, bir silme işleminin neredeyse bir taraftaki tüm verilerle çok dengesiz bir b-ağacı üretebileceğini gösteriyor.


açık ve özlü açıklama ve demo kodu için teşekkürler. Bunu deneyeceğim. Bu cevabı kabul edeceğim. Hala neden satırlar ayrık kümesinde silmek kümelenmiş dizin ile tabloda engelleme nedenini anlamaya çalışıyorum.
jayesh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.