B-Tree viene riequilibrato durante la cancellazione dei dati dalla tabella di SQL Server con un indice cluster?


10

Ho una tabella in un database SQL Server con un indice cluster sulla chiave primaria. La tabella ha 1 milione di righe. Se elimino 10.000 righe dalla tabella, l'indice viene ristrutturato durante l'esecuzione dell'eliminazione?

L'operazione di cancellazione fa parte della procedura memorizzata. Alla volta, più di un client può eseguire la procedura memorizzata, tuttavia ogni singola esecuzione eliminerà il proprio set di righe (identificato in modo univoco dalla chiave primaria). Ricevo il blocco su Blocco tasti (di tipo U) quando più client eseguono la procedura. Il blocco del blocco appartiene a una riga della stessa tabella e non fa parte di alcuna transazione in esecuzione contemporaneamente. Non ci dovrebbero essere blocchi poiché ogni esecuzione sta cercando di eliminare il proprio set di righe. L'escalation del blocco non si verifica poiché è disattivata.

Ho il sospetto che l'operazione di cancellazione debba causare il riequilibrio dell'indice e quindi durante il processo di ristrutturazione può richiedere il blocco delle chiavi su qualsiasi riga della tabella.

Gradirei davvero qualsiasi opinione al riguardo.


Bella domanda e bella supposizione. Sì, quando si elimina il record, l'indice viene ricostruito. Durante il processo di ricostruzione la tabella è bloccata e gli altri utenti non saranno in grado di accedere a quella tabella. stackoverflow.com/questions/6309614/...
KumarHarsh

4
No, l'eliminazione delle righe sull'indice cluster non provoca la ricostruzione dell'indice. Puoi anche pubblicare la query utilizzata per eliminare i dati. Il blocco U viene visualizzato quando la query tenta di trovare i dati che verranno eliminati e infine blocca esclusivamente le righe per eliminarli.
Shanky,

2
Quando si verifica l'eliminazione, viene creato un "buco" oppure è possibile dire spazio quando i dati sono stati rimossi dall'indice cluster. Ciò può creare una bassa densità di pagina e può essere considerato come una frammentazione. Quando l'inserimento avviene su CI riempirà i record sul lato destro e per questo motivo lo spazio potrebbe non essere mai riempito. Ma SQL Server non rimuoverà automaticamente questo spazio. Devi ricostruire l'indice o riorganizzare per riempire questo spazio. Non vi è
alcun

1
@jayesh Non vedo come l'ordine dei nodi in un albero abbia a che fare con il riequilibrio. Un albero a B può essere sbilanciato (a causa di inserti o eliminazioni). L'ordine dei nodi non cambia in questi casi. È solo un albero sbilanciato.
ypercubeᵀᴹ

1
@jayesh Penso che potresti trarre beneficio dalla lettura di alcuni dei documenti MSSQL, poiché penso che la terminologia che stai usando stia confondendo sia te che alcuni di noi.
LowlyDBA

Risposte:


3

Per rispondere alla domanda nel titolo, se l'albero B si è riequilibrato durante un'eliminazione, la risposta sembra essere no, almeno nel seguente caso di test minimo.

La seguente demo esegue i comandi che sono meglio lasciare per un ambiente di test.

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

Questa demo mostra che un'eliminazione può produrre un albero b molto sbilanciato, con praticamente tutti i dati su un lato.


grazie per la spiegazione chiara e concisa e il codice demo. Lo proverò. Accetterò questa risposta. Sto ancora cercando di capire perché l'eliminazione su un insieme disordinato di righe provoca il blocco sulla tabella con indice cluster.
Jay
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.