O B-Tree é reequilibrado durante a exclusão de dados da tabela do SQL Server com um índice em cluster?

10

Eu tenho uma tabela em um banco de dados do SQL Server com um índice em cluster na chave primária. A tabela possui 1 milhão de linhas. Se eu excluir 10 mil linhas da tabela, o índice será reestruturado durante a operação de exclusão?

A operação de exclusão faz parte do procedimento armazenado. Por vez, mais de um cliente pode estar executando o procedimento armazenado, no entanto, cada execução individual excluirá seu próprio conjunto de linhas (identificado exclusivamente pela chave primária). Estou bloqueando o bloqueio de teclas (do tipo U) quando vários clientes executam o procedimento. O bloqueio do bloqueador pertence a uma linha da mesma tabela e não faz parte de nenhuma transação em execução simultânea. Não deve haver nenhum bloqueio, pois cada execução está tentando excluir seu próprio conjunto de linhas. A escalação de bloqueio não está acontecendo, pois está desativada.

Suspeito que a operação de exclusão deva estar causando um reequilíbrio do índice e, portanto, durante o processo de reestruturação, ele pode bloquear a chave em qualquer linha da tabela.

Eu realmente aprecio qualquer opinião sobre isso.

Jayesh
fonte
Boa pergunta e bom palpite. Sim, quando você exclui o registro, o índice é recriado. Durante o processo de reconstrução, a tabela está bloqueada e outro usuário não poderá acessar essa tabela. stackoverflow.com/questions/6309614/…
KumarHarsh
4
NÃO, a exclusão de linhas no índice clusterizado não causa a reconstrução do índice. Você também pode postar a consulta usada para excluir os dados. O bloqueio U ocorre quando a consulta está tentando encontrar dados que serão excluídos e, finalmente, bloqueia exclusivamente as linhas para excluí-los.
shanky
2
Quando a exclusão ocorre, ele cria um "buraco" ou você pode dizer espaço quando os dados foram removidos do índice em cluster. Isso pode criar baixa densidade de página e pode ser considerado como uma fragmentação. Quando a inserção ocorre no IC, ela preenche os registros do lado direito e, por isso, o espaço pode nunca ser preenchido. Mas o SQL Server não removerá automaticamente esse espaço. Você precisa reconstruir o índice ou reorganizar para preencher esse espaço. Não há nenhuma reequilíbrio como tal
shanky
11
@ Jayesh Não vejo como a ordem dos nós em uma árvore tem a ver com o reequilíbrio. Uma árvore B pode ser desequilibrada (devido a inserções ou exclusões). A ordem dos nós não muda nesses casos. É apenas uma árvore desequilibrada.
precisa saber é o seguinte
11
@ Jayesh Acho que você pode se beneficiar da leitura de alguns dos documentos do MSSQL, pois acho que a terminologia que você está usando está confundindo você e alguns de nós.
LowlyDBA

Respostas:

3

Para responder à pergunta no título, se a árvore B se reequilibrou durante uma exclusão, a resposta parece ser negativa, pelo menos no seguinte caso de teste mínimo.

A demonstração a seguir executa comandos que são melhores para um ambiente de teste.

--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 demonstração mostra que uma exclusão pode produzir uma árvore b muito desequilibrada, com praticamente todos os dados de um lado.

Forrest
fonte
obrigado pela explicação clara e concisa e pelo código de demonstração. Eu vou tentar isso. Eu aceito esta resposta. Ainda estou tentando descobrir por que excluir um conjunto separado de linhas causa o bloqueio na tabela com índice clusterizado.
Jayesh #