Por que CREATE INDEX… WITH ONLINE = ON bloqueia o acesso à tabela por um período de minutos?

22

Eu tenho uma tabela existente:

CREATE TABLE dbo.ProofDetails
(
    ProofDetailsID int NOT NULL 
        CONSTRAINT PK_ProofDetails 
        PRIMARY KEY CLUSTERED IDENTITY(1,1)
    , ProofID int NULL
    , IDShownToUser int NULL
    , UserViewedDetails bit NOT NULL 
        CONSTRAINT DF_ProofDetails_UserViewedDetails 
        DEFAULT ((0))
);

Esta tabela possui 150.000.000 de linhas. O sistema está em operação 24x7x365, portanto, não há janelas de manutenção que ocorram regularmente.

Desejo adicionar um índice à tabela e, com a edição Enterprise do SQL Server, devo fazer isso sem bloquear o acesso de gravação à tabela. O comando que eu usei foi:

CREATE INDEX IX_ProofDetails_ProofID_Etc 
ON dbo.ProofDetails (ProofID, IDShownToUser)
INCLUDE (UserViewedDetails)
WITH (ONLINE=ON
    , ALLOW_ROW_LOCKS=ON
    , ALLOW_PAGE_LOCKS=ON
    , FILLFACTOR=100
    , MAXDOP=4
);

Eu executei a instrução sozinha no SSMS, pressionando F5. Ele durou mais de um minuto e começou a bloquear outras sessões. Em seguida, cancelei imediatamente o CREATE INDEXcomando, pois não consigo bloquear outras sessões.

Durante o primeiro minuto, nada estava bloqueando meu CREATE INDEXcomando, sys.dm_exec_requestsmostrou o processo com um tipo de espera CXPACKET- é claro. Não acho que isso seja ruim desde que a operação foi paralelizada.

Não tive muito tempo para inspecionar a saída do sys.dm_exec_requests. Houve apenas uma única linha retornada da consulta WHERE session_id = xxx. As sessões bloqueadas estavam tentando inserir linhas na tabela de destino.

Não sei quanto tempo duraram os bloqueios, exceto para dizer que cancelei a execução da instrução cerca de 2 minutos após o início. Os blocos estavam ocorrendo por cerca de um minuto naquele momento.

Estou entendendo mal a implementação de WITH (ONLINE=ON)? Ou há algo mais que eu precise estar ciente?

O servidor é uma máquina bastante robusta, com 2 processadores Xeon E5-2643 de 3,3 GHz quad-core, 192 GB de RAM e armazenamento SAN com capacidade para mais de 5.000 iops. A CPU normalmente fica abaixo de 20%, a RAM é 93% utilizada, principalmente pelo SQL Server. Não há mais nada em execução na caixa, apenas o Windows Server 2012 e o SQL Server 2012.

Max Vernon
fonte

Respostas:

23

Ao criar um índice com online = on, o processo de criação de índice não será bloqueado ao criar o próprio objeto de índice, mas quando chegar perto do final do processo, ele obterá um bloqueio de modificação de esquema * por um período para realmente adicione o índice à tabela, esse tipo de bloqueio bloqueará todas as operações externas até que o bloqueio seja liberado, o que pode explicar seus problemas de bloqueio.

* Um Sch-Mbloqueio não é necessário para a criação online de um novo índice não clusterizado, embora seja necessário em todos os outros casos. Um novo índice não clusterizado requer apenas um bloqueio compartilhado no nível da tabela durante a fase final, o mesmo que era necessário durante a fase de preparação.

Consulte este White Paper para obter detalhes:

Operações de indexação online no SQL Server 2005

Conforme sugerido por Mushtaq Mohammed em um comentário sobre a questão, veja também:

Unicórnios, arco-íris e operações de índice on-line por Paul Randal

steoleary
fonte