¿Se vuelve a equilibrar B-Tree durante la eliminación de datos de la tabla de SQL Server con un índice agrupado?

10

Tengo una tabla en una base de datos de SQL Server con un índice agrupado en la clave primaria. La tabla tiene 1 millón de filas. Si elimino 10K filas de la tabla, ¿se reestructura el índice durante la operación de eliminación?

La operación de eliminación es parte del procedimiento almacenado. A la vez, más de un cliente puede ejecutar el procedimiento almacenado, sin embargo, cada ejecución individual eliminará su propio conjunto de filas (identificadas de forma exclusiva por la clave primaria). Estoy bloqueando el bloqueo de teclas (de tipo U) cuando varios clientes ejecutan el procedimiento. El bloqueo del bloqueador pertenece a una fila de la misma tabla y no forma parte de ninguna de las transacciones que se ejecutan simultáneamente. No debería haber ningún bloqueo ya que cada ejecución intenta eliminar su propio conjunto de filas. La escalada de bloqueo no ocurre porque está desactivada.

Sospecho que la operación de eliminación debe estar causando que el índice se vuelva a equilibrar y, por lo tanto, durante el proceso de reestructuración, puede bloquear las teclas en cualquier fila de la tabla.

Realmente agradecería cualquier opinión sobre esto.

Jayesh
fuente
Buena pregunta y buena suposición. Sí, cuando elimina el registro, el índice se reconstruye. Durante el proceso de reconstrucción, la tabla está bloqueada y otros usuarios no podrán acceder a esa tabla. stackoverflow.com/questions/6309614/…
KumarHarsh
44
NO, la eliminación de filas en el índice agrupado no causa la reconstrucción del índice. ¿Puede publicar también la consulta utilizada para eliminar los datos? El bloqueo U se produce cuando la consulta intenta encontrar datos que se eliminarán y finalmente bloquea exclusivamente las filas para eliminarlo.
Shanky
2
Cuando ocurre la eliminación, crea un "agujero" o puede decir espacio cuando los datos se eliminaron del índice agrupado. Esto puede crear baja densidad de página y puede considerarse como una fragmentación. Cuando se inserta en CI, llenará los registros en el lado derecho y, debido a esto, es posible que el espacio nunca se llene. Pero SQL Server no eliminará automáticamente este espacio. Tienes que reconstruir el índice o reorganizar para llenar este espacio. NO hay reequilibrio como tal
Shanky
1
@jayesh No veo cómo el orden de los nodos en un árbol tiene que ver con el reequilibrio. Un árbol B puede estar desequilibrado (ya sea por inserciones o eliminaciones). El orden de los nodos no cambia en estos casos. Es solo un árbol desequilibrado.
ypercubeᵀᴹ
1
@jayesh Creo que puede beneficiarse al leer algunos de los documentos de MSSQL, ya que creo que la terminología que está utilizando es confusa tanto para usted como para algunos de nosotros.
LowlyDBA

Respuestas:

3

Para responder a la pregunta en el título, si el árbol B se reequilibró durante una eliminación, la respuesta parece ser no, al menos en el siguiente caso de prueba mínimo.

La siguiente demostración ejecuta comandos que es mejor dejar para un entorno de prueba.

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

Esta demostración muestra que una eliminación puede producir un árbol b muy desequilibrado, con prácticamente todos los datos en un lado.

Para descanso
fuente
Gracias por la explicación clara y concisa y el código de demostración. Probaré esto. Acepto esta respuesta. Todavía estoy tratando de averiguar por qué eliminar en un conjunto disjunto de filas causa el bloqueo en la tabla con índice agrupado.
jayesh