Faça a seguinte reprodução:
USE tempdb;
IF OBJECT_ID(N'dbo.t', N'U') IS NOT NULL
DROP TABLE dbo.t
GO
CREATE TABLE dbo.t
(
id int NOT NULL
PRIMARY KEY
NONCLUSTERED
IDENTITY(1,1)
, col1 datetime NOT NULL
, col2 varchar(800) NOT NULL
, col3 tinyint NULL
, col4 sysname NULL
);
INSERT INTO dbo.t (
col1
, col2
, col3
, col4
)
SELECT TOP(100000)
CONVERT(datetime,
DATEADD(DAY, CONVERT(int, CRYPT_GEN_RANDOM(1)), '2000-01-01 00:00:00'))
, replicate('A', 800)
, sc2.bitpos
, CONVERT(sysname, CHAR(65 + CRYPT_GEN_RANDOM(1) % 26)
+ CHAR(65 + CRYPT_GEN_RANDOM(1) % 26)
+ CHAR(65 + CRYPT_GEN_RANDOM(1) % 26))
FROM sys.syscolumns sc
CROSS JOIN sys.syscolumns sc2;
Aqui estou adicionando um índice clusterizado em um conjunto de colunas que não são exclusivas e um índice típico não clusterizado de coluna única:
CREATE CLUSTERED INDEX t_cx
ON dbo.t (col1, col2, col3);
CREATE INDEX t_c1 ON dbo.t(col4);
Essa consulta força o SQL Server a fazer uma pesquisa no índice clusterizado. Por favor, perdoe o uso da dica de índice, foi a maneira mais rápida de obter a reprodução:
SELECT id
, col1
, col2
, col3
FROM dbo.t aad WITH (INDEX = t_c1)
WHERE col4 = N'JSB'
AND col1 > N'2019-05-30 00:00:00';
O plano de consulta real mostra uma coluna inexistente na Lista de saída para a verificação de índice não clusterizado:
Aparentemente, isso representa o unificador usado no índice clusterizado não exclusivo. É esse o caso? Uma coluna com esse nome é sempre o unificador de índice clusterizado?
Sim.
Cada linha no índice não clusterizado deve ser associada a exatamente uma linha na tabela base para que as Pesquisas de Marcador (RID ou Chave) funcionem corretamente. Este mapeamento é fornecido pelo "localizador de linha".
Para tabelas de heap, o localizador de linha é o RID. Para tabelas de armazenamento de linhas agrupadas, é a chave de agrupamento (incluindo o unificador quando necessário).
Para que a Pesquisa de Chave em seu plano funcione, ela deve ter acesso ao localizador de linha. Isso inclui o uniquifier , portanto, ele deve ser emitido pela varredura de índice não clusterizado.
O unificador é armazenado na parte de comprimento variável da linha, de modo que só ocupa espaço quando necessário (ou seja, quando uma chave duplicada realmente existe).
Sim. A coluna unificadora é sempre nomeada
UniqXXXX
. O localizador de linha associado às tabelas de heap é denominadoBmkXXXX
. O localizador de linha para uma tabela columnstore é denominadoColStoreLocXXXX
.Observando o unificador
É possível observar diretamente os valores do unificador nas versões do SQL Server que contêm um
query_trace_column_values
Extended Event funcional .Este evento não documentado e sem suporte está no canal Debug . Ele foi introduzido com o SQL Server 2016 e parou de funcionar em torno do CU11 do SQL Server 2017.
Por exemplo:
Tem o plano:
Ele produz uma saída de evento como a seguinte no SQL Server 2016:
Para que o SQL Server crie um índice clusterizado não exclusivo , uma "coluna" oculta é adicionada à estrutura física do índice clusterizado. Essa coluna oculta é conhecida como uniqifier e, como o próprio nome indica, fornece um mecanismo para garantir que cada linha no índice clusterizado seja exclusiva.
Quando você vê essa coluna aparecer em um plano de consulta, é um ótimo indicador de que as colunas de chave de clustering não foram definidas como exclusivas. Possivelmente isso ocorre porque a combinação de colunas é conhecida por não ser única. Também é possível que o designer da tabela simplesmente tenha esquecido de adicionar o
UNIQUE
qualificador àCREATE CLUSTERED INDEX
instrução.De fato, se recriarmos o repro acima com um índice clusterizado exclusivo, a
Uniq1002
coluna não aparecerá mais no plano de consulta:Aqui está o índice clusterizado UNIQUE:
E a consulta:
O plano agora mostra isso para as colunas de saída de varredura de índice não clusterizado:
Quando um índice clusterizado não exclusivo é criado, o uniqifier é adicionado automaticamente. O uniqifier também é adicionado a todos os índices não agrupados, mesmo que você não possa "vê-lo" observando as propriedades do índice ou "criando scripts" do índice.
O uniqifier é uma coluna de quatro bytes contendo um inteiro que é incrementado automaticamente nos bastidores para cada linha inserida na tabela. A primeira linha inserida não requer um unificador; apenas as linhas adicionadas após a primeira linha têm o uniqifier presente.