É assim que minha mesa está:
CREATE TABLE [dbo].[ClosedTaskCustomFields](
[ClosedTaskId] [uniqueidentifier] NOT NULL,
[CustomFieldId] [uniqueidentifier] NOT NULL,
[Value] [nvarchar](450) NULL
...
CONSTRAINT [PK_ClosedTaskCustomFields] PRIMARY KEY CLUSTERED
(
[ClosedTaskId] ASC,
[CustomFieldId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
E também tenho esse índice para ingressar na tabela ClosedTask:
CREATE NONCLUSTERED INDEX [IX_ClosedTaskCustomFields_ClosedTaskId] ON [dbo].[ClosedTaskCustomFields]
(
[ClosedTaskId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
Mas não consigo entender por que essa consulta lê toda a tabela ClosedTaskCustomFields para ingressar no ClosedTask se eu tiver índice.
select count(1) from ClosedTaskCustomFields ctcf
join ClosedTask c on c.id = ctcf.ClosedTaskId
where c.State = 'Rejected'
-- Result count is 50k.
O SQL Server escolhe o plano que parece mais barato com base em suas estimativas. Isso significa que o plano que você tem em mente, com busca de índice em ambas as tabelas, teria um custo mais alto. Você pode testar isso sozinho usando uma
FORCESEEK
dica.Observe que um custo estimado mais alto não significa necessariamente que o plano seria executado mais lentamente do que a alternativa escolhida no seu hardware específico.
Há muitos motivos pelos quais o plano mostrado tem um custo menor:
Você pode descobrir que o otimizador escolhe naturalmente o plano de busca com uma
MAXDOP 1
dica ou um limite de custo mais alto para paralelismo em geral. Parece que você definiu o valor padrão de 5, que muitas pessoas consideram muito baixo atualmente.Caso contrário, você terá a maneira normal de substituir as opções do otimizador: usando uma dica como
FORCESEEK
. Eu não me incomodaria, a menos que a consulta seja crucial e economizar alguns milissegundos extras seja importante.Para obter mais informações sobre bitmaps em modo de linha, consulte meu artigo Bitmap Magic (ou… como o SQL Server usa filtros de bitmap).
O SQL-Server usou uma busca de índice
ClosedTask
noState
índice (provavelmente porque esta coluna é usada na condição) e uma varredura de índice emClosedTaskCustomFields
.Se
State
fosse muito seletivo, essa consulta selecionaria apenas uma pequena fração dos registros em cada tabela. Mas provavelmente não é, porque você tem apenas alguns estados. Portanto, provavelmente é mais barato apenas fazer uma varredura no índice na tabela de campos personalizados e pular o número relativamente pequeno de registros não correspondentes do que pesquisar. Uma busca de índice requer vários acessos ao disco para detalhar a árvore de índice. Portanto, não é necessariamente barato.As coisas eram diferentes se
State
fosse muito seletivo, ou seja, se tivesse muitos estados.Mas isso é apenas uma suposição, pois não conheço o algoritmo utilizado pelo otimizador de consultas.