L'arborescence B est-elle rééquilibrée lors de la suppression des données de la table SQL Server avec un index cluster?

10

J'ai une table dans une base de données SQL Server avec un index cluster sur la clé primaire. Le tableau comporte 1 million de lignes. Si je supprime 10 000 lignes de la table, l'index est-il restructuré pendant l'opération de suppression?

L'opération de suppression fait partie de la procédure stockée. À la fois, plusieurs clients peuvent exécuter la procédure stockée, mais chaque exécution individuelle supprimera son propre ensemble de lignes (identifié de manière unique par la clé primaire). J'obtiens un blocage sur le verrouillage des touches (de type U) lorsque plusieurs clients exécutent la procédure. Le verrou de blocage appartient à une ligne de la même table et ne fait partie d'aucune des transactions exécutées simultanément. Il ne devrait pas y avoir de blocage car chaque exécution tente de supprimer son propre ensemble de lignes. L'escalade des verrous ne se produit pas car elle est désactivée.

Je suppose que l'opération de suppression doit provoquer un rééquilibrage de l'index et, par conséquent, pendant le processus de restructuration, il peut prendre le verrouillage des touches sur n'importe quelle ligne de la table.

J'apprécierais vraiment toute opinion à ce sujet.

jayesh
la source
Belle question et belle supposition. Oui, lorsque vous supprimez un enregistrement, l'index est reconstruit. Pendant la reconstruction, la table est verrouillée et aucun autre utilisateur ne pourra accéder à cette table. stackoverflow.com/questions/6309614/…
KumarHarsh
4
NON, la suppression des lignes de l'index cluster ne provoque pas la reconstruction de l'index. Pouvez-vous également publier la requête utilisée pour supprimer les données. Le verrou U intervient lorsque la requête tente de trouver des données qui seront supprimées et verrouille finalement exclusivement les lignes pour les supprimer.
Shanky
2
Lorsque la suppression se produit, elle crée un "trou" ou vous pouvez dire l'espace car les données ont été supprimées de l'index cluster. Cela peut créer une faible densité de pages et peut être considéré comme une fragmentation. Lorsque l'insertion se produit sur CI, elle remplira les enregistrements sur le côté droit et pour cette raison, l'espace peut ne jamais être rempli. Mais SQL Server ne supprimera pas automatiquement cet espace. Vous devez reconstruire l'index ou réorganiser pour remplir cet espace. Il n'y a PAS de rééquilibrage en tant que tel
Shanky
1
@jayesh Je ne vois pas comment l'ordre des nœuds dans un arbre a à voir avec le rééquilibrage. Un arbre B peut être déséquilibré (soit à cause d'insertions ou de suppressions). L'ordre des nœuds ne change pas dans ces cas. C'est juste un arbre déséquilibré.
ypercubeᵀᴹ
1
@jayesh Je pense que vous pourriez bénéficier de la lecture de certains documents MSSQL, car je pense que la terminologie que vous utilisez est source de confusion pour vous et certains d'entre nous.
LowlyDBA

Réponses:

3

Pour répondre à la question dans le titre, si l'arbre B a été rééquilibré lors d'une suppression, la réponse semble être non, du moins dans le cas de test minimal suivant.

La démo suivante exécute les commandes qu'il vaut mieux laisser pour un environnement de 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

Cette démo montre qu'une suppression peut produire un arbre b très déséquilibré, avec pratiquement toutes les données d'un côté.

Forrest
la source
merci pour l'explication claire et concise et le code de démonstration. Je vais essayer ça. J'accepte cette réponse. J'essaie toujours de comprendre pourquoi la suppression sur un ensemble de lignes disjoint provoque un blocage sur la table avec un index cluster.
jayesh