To kolejna zagadka optymalizatora zapytań.
Może po prostu przeszacowuję optymalizatory zapytań, a może coś mi brakuje - więc zamieszczam to.
Mam prosty stół
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])
z indeksem i kilkoma tysiącami wierszy, Number
równomiernie rozmieszczonymi w wartościach 0, 1 i 2.
Teraz to zapytanie:
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;
indeks szuka IX_Number
zgodnie z oczekiwaniami.
Jeśli klauzula gdzie jest
WHERE P.Name = 'one';
staje się jednak skanem.
Klauzula przypadku jest oczywiście bijectionem, więc teoretycznie optymalizacja powinna umożliwić odjęcie pierwszego planu zapytania od drugiego zapytania.
Nie jest to również czysto akademickie: zapytanie jest inspirowane tłumaczeniem wartości wyliczeniowych na ich przyjazne nazwy.
Chciałbym usłyszeć od kogoś, kto wie, czego można się spodziewać po optymalizatorach zapytań (a konkretnie w Sql Server): czy po prostu oczekuję zbyt wiele?
Pytam, tak jak kiedyś miałem przypadki, w których niewielka zmiana zapytania sprawiłaby, że optymalizacja nagle wyszła na jaw.
Używam Sql Server 2016 Developer Edition.
Interpretuję to pytanie jako ogólnie zainteresowane optymalizatorami, ale ze szczególnym zainteresowaniem dla SQL Server. Przetestowałem twój scenariusz z db2 LUW V11.1:
Optymalizator w DB2 przepisuje drugie zapytanie na pierwsze:
Plan wygląda następująco:
Nie wiem wiele o innych optymalizatorach, ale mam wrażenie, że optymalizator DB2 jest uważany za całkiem dobry nawet wśród konkurentów.
źródło
W tym konkretnym zapytaniu głupota jest nawet mieć
CASE
instrukcję. Filtrujesz do jednego konkretnego przypadku! Być może jest to tylko szczegół konkretnego przykładowego zapytania, które podałeś, ale jeśli nie, możesz napisać to zapytanie, aby uzyskać równoważne wyniki:To da ci dokładnie ten sam zestaw wyników, a ponieważ i tak już mocno kodujesz wartości w
CASE
instrukcji, nie tracisz tutaj żadnej łatwości konserwacji.źródło
CASE
oświadczenie, ponieważ ORM robią takie rzeczy. Głupie jest to, że nie rozpoznałeś tych prostych aspektów problemu ... (jak to jest, że jesteś pośrednio nazywany bezmyślnym?)CASE
stwierdzenie można całkowicie wyeliminować bez wad. Od kursu nie może być nieznane czynniki, ale są nieokreślone.