Eu tenho uma tabela com um nonclustered index
em um datetime2
campo.
Nessa mesma tabela tenho um campo (char[1])
que é usado para deletar registros logicamente e pode ter 2 valores distintos: A
(ativo) ou D
(excluído).
Existem 451.047 registros com o datetime2
campo definido como, NULL
mas apenas 7.095 estão marcados como A
.
Toda consulta na aplicação procura apenas registros ativos , então, toda consulta que está procurando NULLs
no campo datetime estava recebendo estimativas muito ruins e, com isso, planos de execução ruins.
Decidi então criar um índice não clusterizado filtrado, mas as estimativas ainda estavam incorretas:
Parece que ainda recebo as estimativas antigas, mesmo que a consulta esteja usando corretamente o índice filtrado. Alguém sabe o motivo deste comportamento?
Estas são as novas estatísticas do índice filtrado:
Definição da tabela:
CREATE TABLE [TYDATPRD].[HAND00F](
[STDRECSTS] [char](1) NULL,
[HDHAND] [numeric](14, 0) IDENTITY(1,1) NOT NULL,
[HDCHKINDT] [datetime2](7) NULL,
--lots of other columns which I don't think are needed
CONSTRAINT [PK_TYDATPRD_HAND00F] PRIMARY KEY CLUSTERED (
[HDHAND] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [DATA]
) ON [DATA]
Definição de índice filtrado não clusterizado:
CREATE NONCLUSTERED INDEX [IX_HAND00F_HDCHKINDT] ON [TYDATPRD].[HAND00F] (
[HDCHKINDT] ASC
)
WHERE [STDRECSTS]='A'
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [INDEXES]
GO
Isso não é intuitivo, mas tente adicionar a
char[1]
coluna à definição do índice filtrado:Em meus testes, isso levou às estimativas corretas.
A propósito, notei que os planos em sua pergunta eram diferentes - um estava devidamente parametrizado e o outro tinha uma constante. Tenha muito cuidado sobre como você está fazendo testes locais com variáveis locais e constantes digitadas, especialmente se no mundo real isso for feito por parâmetros para procedimentos armazenados.
Além disso, tenha muito cuidado com os literais case - na cláusula where como
= 'a'
e= 'A'
gerarão planos diferentes se não forem parametrizados, porque o texto da consulta é diferente. Não importa que em alguns agrupamentos eles não produzam os mesmos resultados. (E essachar(1)
coluna precisa permitirNULL
?)