Esse é outro enigma do otimizador de consulta.
Talvez eu esteja apenas superestimando os otimizadores de consulta ou talvez esteja perdendo alguma coisa - por isso estou publicando isso.
Eu tenho uma mesa simples
CREATE TABLE [dbo].[MyEntities](
[Id] [uniqueidentifier] NOT NULL,
[Number] [int] NOT NULL,
CONSTRAINT [PK_dbo.MyEntities] PRIMARY KEY CLUSTERED ([Id])
)
CREATE NONCLUSTERED INDEX [IX_Number] ON [dbo].[MyEntities] ([Number])
com um índice e algumas milhares de linhas, Number
sendo distribuídos igualmente nos valores 0, 1 e 2.
Agora esta consulta:
SELECT * FROM
(SELECT
[Extent1].[Number] AS [Number],
CASE
WHEN (0 = [Extent1].[Number]) THEN 'one'
WHEN (1 = [Extent1].[Number]) THEN 'two'
WHEN (2 = [Extent1].[Number]) THEN 'three'
ELSE '?'
END AS [Name]
FROM [dbo].[MyEntities] AS [Extent1]
) P
WHERE P.Number = 0;
um índice procura IX_Number
como seria de esperar.
Se a cláusula where for
WHERE P.Name = 'one';
no entanto, torna-se uma varredura.
A cláusula de caso é obviamente uma bijeção, portanto, em teoria, uma otimização deve ser possível deduzir o primeiro plano de consulta da segunda consulta.
Também não é puramente acadêmico: a consulta é inspirada na tradução de valores enum para seus respectivos nomes amigáveis.
Eu gostaria de ouvir de alguém que sabe o que pode ser esperado dos otimizadores de consulta (e especificamente do Sql Server): Estou simplesmente esperando demais?
Estou perguntando como tive casos anteriores em que uma ligeira variação de uma consulta faria uma otimização aparecer de repente.
Estou usando o Sql Server 2016 Developer Edition.
Interpreto a pergunta como se você estivesse interessado em otimizadores em geral, mas com um interesse especial pelo SQL Server. Testei seu cenário com o db2 LUW V11.1:
O otimizador no DB2 reescreve a segunda consulta na primeira:
O plano se parece com:
Não sei muito sobre outros otimizadores, mas sinto que o otimizador do DB2 é considerado muito bom, mesmo entre os concorrentes.
fonte
Nesta consulta em particular, é muito bobo até ter uma
CASE
declaração. Você está filtrando para um caso específico! Talvez este seja apenas um detalhe da consulta de exemplo específica que você forneceu, mas, se não, você pode escrever essa consulta para obter resultados equivalentes:Isso fornecerá exatamente o mesmo conjunto de resultados e, como você já está codificando os valores em uma
CASE
instrução de qualquer maneira, não estará perdendo nenhuma manutenção aqui.fonte
CASE
declaração, porque as ORMs fazem esse tipo de coisa. Que bobagem é que você não reconhecer essas facetas simples do problema ... (como é que para ser indiretamente chamado desmiolado?)CASE
declaração poderá ser eliminada totalmente sem inconvenientes. Claro que pode haver fatores desconhecidos, mas eles não são especificados.