Ceci est une autre énigme d'optimiseur de requête.
Peut-être que je surestime simplement les optimiseurs de requête, ou peut-être qu'il me manque quelque chose - je le mets donc là.
J'ai une table 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])
avec un index et quelques milliers de lignes, Number
réparties uniformément dans les valeurs 0, 1 et 2.
Maintenant, cette requête:
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;
recherche un indice IX_Number
comme on pourrait s'y attendre.
Si la clause where est
WHERE P.Name = 'one';
cependant, cela devient un scan.
La clause de cas est évidemment une bijection, donc en théorie une optimisation devrait être possible pour déduire le premier plan de requête de la seconde requête.
Ce n'est pas non plus purement académique: la requête est inspirée de la traduction des valeurs d'énumération en leurs noms conviviaux respectifs.
J'aimerais entendre quelqu'un qui sait ce que l'on peut attendre des optimiseurs de requêtes (et en particulier celui de Sql Server): est-ce que j'attends simplement trop?
Je demande comme j'avais des cas auparavant où une légère variation d'une requête ferait soudainement apparaître une optimisation.
J'utilise Sql Server 2016 Developer Edition.
J'interprète la question comme si vous êtes intéressé par les optimiseurs en général, mais avec un intérêt particulier pour SQL Server. J'ai testé votre scénario avec db2 LUW V11.1:
L'optimiseur dans DB2 réécrit la deuxième requête dans la première:
Le plan ressemble à:
Je ne connais pas grand-chose aux autres optimiseurs, mais j'ai l'impression que l'optimiseur DB2 est considéré comme assez bon, même parmi les concurrents.
la source
Dans cette requête particulière, il est assez stupide d'avoir même une
CASE
déclaration. Vous filtrez vers un cas particulier! Peut-être que ce n'est qu'un détail de l'exemple de requête particulier que vous avez donné, mais sinon, vous pouvez écrire cette requête pour obtenir des résultats équivalents:Cela vous donnera exactement le même jeu de résultats, et puisque vous êtes déjà en train de coder en dur des valeurs dans une
CASE
instruction, vous ne perdez aucune maintenance ici.la source
CASE
déclaration du tout, parce que les ORM font ce genre de chose. Ce qui est stupide, c'est que vous n'avez pas reconnu ces facettes simples du problème ... (comment ça s'appelle indirectement sans cervelle?)CASE
énoncé peut être entièrement éliminé sans inconvénient. Bien sûr, il peut y avoir des facteurs inconnus, mais ils ne sont pas spécifiés.