Vamos lançar um milhão de linhas em uma tabela temporária, juntamente com algumas colunas:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (PK)
);
INSERT INTO #174860 WITH (TABLOCK)
SELECT RN
, RN % 1000
, RN % 10000
FROM
(
SELECT TOP 1000000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values v1,
master..spt_values v2
) t;
CREATE INDEX IX_174860_IX ON #174860 (COL1) INCLUDE (COL2);
Aqui eu tenho um índice clusterizado (por padrão) na PK
coluna. Há um índice não clusterizado COL1
que possui uma coluna-chave de COL1
e inclui COL2
.
Considere a seguinte consulta:
SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Aqui não estou usando BETWEEN
porque Aaron Bertrand está por aí com essa questão.
Como o SQL Server deve otimizar essa consulta? Bem, eu sei que o filtro PK
ativado reduzirá o conjunto de resultados para cinco linhas. O servidor SQL pode usar o índice em cluster para ir para essas cinco linhas em vez de ler todos os milhões de linhas da tabela. No entanto, o índice clusterizado tem apenas a coluna PK como uma coluna-chave. Depois que a linha é lida na memória, precisamos aplicar o filtro COL2
. Aqui, PK
é um predicado de busca e COL2
é um predicado.
O SQL Server localiza cinco linhas usando o predicado de busca e reduz ainda mais essas cinco linhas para uma linha com o predicado normal.
Se eu definir o índice clusterizado de maneira diferente:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
E execute a mesma consulta, obtenho resultados diferentes:
Nesse caso, o SQL Server pode procurar usando as duas colunas na WHERE
cláusula. Exatamente uma linha é lida da tabela usando as colunas-chave.
Para mais um exemplo, considere esta consulta:
SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
O índice IX_174860_IX é um índice de cobertura porque contém todas as colunas necessárias para a consulta. No entanto, apenas COL1
é uma coluna chave. O SQL Server pode procurar com essa coluna encontrar as 1000 linhas com um COL1
valor correspondente . Ele pode filtrar ainda mais essas linhas na COL2
coluna para reduzir o resultado final definido para 0 linhas.