No armazenamento orientado a linhas do SQL Server, os índices clusterizados e não clusterizados são organizados como árvores B.
( Fonte da imagem )
A principal diferença entre índices agrupados e índices não agrupados é que o nível folha do índice agrupado é a tabela. Isso tem duas implicações.
- As linhas nas páginas de folha de índice em cluster sempre contêm algo para cada uma das colunas (não esparsas) da tabela (o valor ou um ponteiro para o valor real).
- O índice clusterizado é a cópia principal de uma tabela.
Os índices não agrupados também podem fazer o ponto 1 usando a INCLUDE
cláusula (Desde o SQL Server 2005) para incluir explicitamente todas as colunas não-chave, mas são representações secundárias e sempre há outra cópia dos dados (a própria tabela).
CREATE TABLE T
(
A INT,
B INT,
C INT,
D INT
)
CREATE UNIQUE CLUSTERED INDEX ci ON T(A,B)
CREATE UNIQUE NONCLUSTERED INDEX nci ON T(A,B) INCLUDE (C,D)
Os dois índices acima serão quase idênticos. Com as páginas de índice de nível superior que contêm valores para as colunas-chave A,B
e as páginas de nível de folha que contêmA,B,C,D
Pode haver apenas um índice em cluster por tabela, porque as próprias linhas de dados podem ser classificadas em apenas uma ordem.
A citação acima dos manuais online do SQL Server causa muita confusão
Na minha opinião, seria muito melhor redigido como.
Pode haver apenas um índice em cluster por tabela, porque as linhas no nível da folha do índice em cluster são as linhas da tabela.
A cotação on-line dos livros não está incorreta, mas você deve deixar claro que a "classificação" de índices não agrupados e agrupados não é lógica. Se você ler as páginas no nível da folha seguindo a lista vinculada e ler as linhas na página na ordem da matriz de slots, você lerá as linhas de índice na ordem classificada, mas fisicamente as páginas podem não ser classificadas. A crença comum de que, com um índice em cluster, as linhas sempre são armazenadas fisicamente no disco na mesma ordem em que a chave de índice é falsa.
Isso seria uma implementação absurda. Por exemplo, se uma linha é inserida no meio de uma tabela de 4 GB, o SQL Server não precisa copiar 2 GB de dados no arquivo para liberar espaço para a linha recém-inserida.
Em vez disso, ocorre uma divisão da página. Cada página no nível folha dos índices em cluster e não em cluster tem o endereço ( File:Page
) da página seguinte e anterior em ordem lógica. Essas páginas não precisam ser contíguas ou em ordem de chave.
por exemplo, a cadeia de páginas vinculada pode ser 1:2000 <-> 1:157 <-> 1:7053
Quando ocorre uma divisão de página, uma nova página é alocada de qualquer lugar do grupo de arquivos (de uma extensão mista, para tabelas pequenas ou de uma extensão uniforme não vazia pertencente a esse objeto ou de uma extensão uniforme recém-alocada). Pode até não estar no mesmo arquivo se o grupo de arquivos contiver mais de um.
O grau em que a ordem lógica e a contiguidade diferem da versão física idealizada é o grau de fragmentação lógica.
Em um banco de dados recém-criado com um único arquivo, executei o seguinte.
CREATE TABLE T
(
X TINYINT NOT NULL,
Y CHAR(3000) NULL
);
CREATE CLUSTERED INDEX ix
ON T(X);
GO
--Insert 100 rows with values 1 - 100 in random order
DECLARE @C1 AS CURSOR,
@X AS INT
SET @C1 = CURSOR FAST_FORWARD
FOR SELECT number
FROM master..spt_values
WHERE type = 'P'
AND number BETWEEN 1 AND 100
ORDER BY CRYPT_GEN_RANDOM(4)
OPEN @C1;
FETCH NEXT FROM @C1 INTO @X;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO T (X)
VALUES (@X);
FETCH NEXT FROM @C1 INTO @X;
END
Em seguida, verifique o layout da página com
SELECT page_id,
X,
geometry::Point(page_id, X, 0).STBuffer(1)
FROM T
CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
ORDER BY page_id
Os resultados estavam por todo o lado. A primeira linha na ordem das chaves (com o valor 1 - destacada com a seta abaixo) estava quase na última página física.
A fragmentação pode ser reduzida ou removida reconstruindo ou reorganizando um índice para aumentar a correlação entre ordem lógica e ordem física.
Depois de correr
ALTER INDEX ix ON T REBUILD;
Eu tenho o seguinte
Se a tabela não tiver um índice clusterizado, ela será chamada de heap.
Os índices não clusterizados podem ser criados em um heap ou em um índice clusterizado. Eles sempre contêm um localizador de linhas de volta à tabela base. No caso de um heap, esse é um identificador de linha físico (rid) e consiste em três componentes (Arquivo: Página: Slot). No caso de um índice em cluster, o localizador de linhas é lógico (a chave de índice em cluster).
Para o último caso, se o índice não agrupado já incluir naturalmente as colunas-chave do IC como colunas-chave NCI ou INCLUDE
-d, nada será adicionado. Caso contrário, as colunas-chave do IC ausentes serão adicionadas silenciosamente ao NCI.
O SQL Server sempre garante que as colunas-chave sejam exclusivas para os dois tipos de índice. O mecanismo no qual isso é imposto para índices não declarados como exclusivos difere entre os dois tipos de índice.
Os índices agrupados são uniquifier
adicionados a todas as linhas com valores-chave que duplicam uma linha existente. Este é apenas um número inteiro ascendente.
Para índices não agrupados em cluster não declarados como exclusivos, o SQL Server adiciona silenciosamente o localizador de linhas à chave de índice não agrupado. Isso se aplica a todas as linhas, não apenas àquelas que são realmente duplicadas.
A nomenclatura em cluster vs não em cluster também é usada para índices de armazenamento de colunas. O artigo Aprimoramentos nos armazenamentos de colunas do SQL Server declara
Embora os dados do armazenamento de colunas não sejam realmente "agrupados" em nenhuma chave, decidimos manter a convenção tradicional do SQL Server de se referir ao índice primário como índice agrupado.