Dies ist ein weiteres Rätsel des Abfrageoptimierers.
Vielleicht überschätze ich nur die Abfrageoptimierer, oder vielleicht fehlt mir etwas - also stelle ich es da raus.
Ich habe einen einfachen Tisch
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])
mit einem Index und einigen tausend Zeilen, Number
die gleichmäßig in den Werten 0, 1 und 2 verteilt sind.
Nun diese Abfrage:
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;
Sucht ein Index so, IX_Number
wie man es erwarten würde?
Wenn die where-Klausel ist
WHERE P.Name = 'one';
Es wird jedoch ein Scan.
Die case-Klausel ist offensichtlich eine Bijektion, daher sollte theoretisch eine Optimierung möglich sein, um den ersten Abfrageplan von der zweiten Abfrage abzuleiten.
Es ist auch nicht rein akademisch: Die Abfrage ist inspiriert von der Übersetzung von Enum-Werten in ihre jeweiligen Anzeigenamen.
Ich würde gerne von jemandem hören, der weiß, was von Abfrageoptimierern erwartet werden kann (und insbesondere von dem in SQL Server): Erwarte ich einfach zu viel?
Ich frage, wie ich es zuvor getan habe, in denen eine geringfügige Variation einer Abfrage eine Optimierung plötzlich ans Licht bringen würde.
Ich verwende SQL Server 2016 Developer Edition.
Ich interpretiere die Frage so, dass Sie an Optimierern im Allgemeinen interessiert sind, aber mit einem besonderen Interesse für SQL Server. Ich habe Ihr Szenario mit db2 LUW V11.1 getestet:
Das Optimierungsprogramm in DB2 schreibt die zweite Abfrage in die erste um:
Der Plan sieht aus wie:
Ich weiß nicht viel über andere Optimierer, aber ich habe das Gefühl, dass der DB2-Optimierer selbst unter Wettbewerbern als ziemlich gut angesehen wird.
quelle
In dieser speziellen Abfrage ist es ziemlich dumm, überhaupt eine
CASE
Aussage zu haben. Sie filtern auf einen bestimmten Fall! Vielleicht ist dies nur ein Detail der speziellen Beispielabfrage, die Sie gegeben haben. Wenn nicht, können Sie diese Abfrage schreiben, um gleichwertige Ergebnisse zu erhalten:Dadurch erhalten Sie genau die gleiche Ergebnismenge, und da Sie ohnehin bereits Werte in einer
CASE
Anweisung fest codieren , verlieren Sie hier keine Wartbarkeit.quelle
CASE
Aussage zu haben, weil ORMs so etwas tun. Was albern ist, dass Sie diese einfachen Facetten des Problems nicht erkannt haben ... (wie ist das, wenn Sie indirekt als hirnlos bezeichnet werden?)CASE
Aussage ohne Nachteil vollständig beseitigt werden kann. Von Natürlich könnte es unbekannte Faktoren sein, aber sie sind nicht spezifiziert.