Este es otro enigma del optimizador de consultas.
Tal vez solo estoy sobreestimando los optimizadores de consultas, o tal vez me falta algo, así que lo estoy publicando.
Tengo una mesa simple
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])
con un índice y unos miles de filas allí, Number
distribuidos uniformemente en los valores 0, 1 y 2.
Ahora 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;
busca un índice IX_Number
como cabría esperar.
Si la cláusula where es
WHERE P.Name = 'one';
Sin embargo, se convierte en un escaneo.
La cláusula del caso es obviamente una biyección, por lo que en teoría una optimización debería ser posible deducir el primer plan de consulta de la segunda consulta.
Tampoco es puramente académico: la consulta se inspira en la traducción de valores de enumeración a sus respectivos nombres descriptivos.
Me gustaría saber de alguien que sepa qué se puede esperar de los optimizadores de consultas (y específicamente el que está en Sql Server): ¿Simplemente estoy esperando demasiado?
Pregunto, ya que tenía casos antes, donde una ligera variación de una consulta haría que una optimización saliera a la luz de repente.
Estoy usando Sql Server 2016 Developer Edition.
Interpreto la pregunta como si estuviera interesado en los optimizadores en general, pero con un interés especial para SQL Server. Probé su escenario con db2 LUW V11.1:
El optimizador en DB2 reescribe la segunda consulta a la primera:
El plan se ve así:
No sé mucho sobre otros optimizadores, pero tengo la sensación de que el optimizador de DB2 se considera bastante bueno incluso entre los competidores.
fuente
En esta consulta en particular, es bastante tonto incluso tener una
CASE
declaración. ¡Estás filtrando a un caso en particular! Quizás esto sea solo un detalle de la consulta de ejemplo particular que ha dado, pero si no, puede escribir esta consulta para obtener resultados equivalentes:Esto le dará exactamente el mismo conjunto de resultados, y dado que de
CASE
todos modos ya está codificando valores en una declaración, no está perdiendo ninguna capacidad de mantenimiento aquí.fuente
CASE
declaración en absoluto, porque los ORM hacen ese tipo de cosas. Lo tonto es que no reconociste estas simples facetas del problema ... (¿cómo es eso de ser indirectamente llamado sin cerebro?)CASE
declaración se puede eliminar por completo sin inconvenientes. Por supuesto , puede haber factores desconocidos, pero no están especificados.