Überprüfen Sie diese Abfrage. Es ist ziemlich einfach (siehe Ende des Beitrags für Tabellen- und Indexdefinitionen und ein Reproskript):
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Hinweis: Mit "AND 1 = (SELECT 1)" soll nur verhindert werden, dass diese Abfrage automatisch parametrisiert wird. Ich hatte den Eindruck, dass dies das Problem verwirrt hat. Es wird jedoch derselbe Plan mit oder ohne diese Klausel erstellt
Und hier ist der Plan ( fügen Sie den Plan-Link ein) :
Da es dort eine "Top 1" gibt, war ich überrascht, den Stream-Aggregat-Operator zu sehen. Es scheint mir nicht notwendig zu sein, da es garantiert nur eine Reihe gibt.
Um diese Theorie zu testen, habe ich diese logisch äquivalente Abfrage ausprobiert:
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
Hier ist der Plan für diesen ( fügen Sie den Plan-Link ein ):
Sicher genug, die Gruppe nach Plan kommt ohne den Stream-Aggregat-Operator aus.
Beachten Sie, dass beide Abfragen ab dem Ende des Index "Rückwärts" lesen und eine "Top 1" ausführen, um die maximale Revision zu erhalten.
Was vermisse ich hier? Funktioniert das Stream-Aggregat tatsächlich in der ersten Abfrage oder sollte es beseitigt werden können (und es ist nur eine Einschränkung des Optimierers, die es nicht ist)?
Übrigens stelle ich fest, dass dies kein unglaublich praktisches Problem ist (beide Abfragen melden 0 ms CPU und verstrichene Zeit). Ich bin nur neugierig auf die Interna / das Verhalten, das hier gezeigt wird.
Hier ist der Setup-Code, den ich ausgeführt habe, bevor ich die beiden obigen Abfragen ausgeführt habe:
DROP TABLE IF EXISTS dbo.TheOneders;
GO
CREATE TABLE dbo.TheOneders
(
Id INT NOT NULL,
Revision SMALLINT NOT NULL,
Something NVARCHAR(23),
CONSTRAINT PK_TheOneders PRIMARY KEY NONCLUSTERED (Id, Revision)
);
GO
INSERT INTO dbo.TheOneders
(Id, Revision, Something)
SELECT DISTINCT TOP 1000
1, m.message_id, 'Do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);
INSERT INTO dbo.TheOneders
(Id, Revision, Something)
SELECT DISTINCT TOP 100
2, m.message_id, 'Do that thing you do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);
GO
quelle