Bu sorguyu kontrol edin. Oldukça basit (tablo ve dizin tanımları ve repro komut dosyası için gönderinin sonuna bakın):
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Not: "VE 1 = (SEÇ 1), bu sorgunun sorunu otomatik olarak değiştirdiğini ve bununla ilgili kafa karıştırıcı olduğunu hissettiğimi korumaktır - aslında aynı planı olsa da olmasa da aynı planı alır
Ve işte plan ( plan bağlantısını yapıştırın) :
Orada bir "ilk 1" olduğundan, akış toplama operatörü görmek için sürpriz oldu. Benim için gerekli görünmüyor, çünkü sadece bir sıra olması garanti ediliyor.
Bu teoriyi test etmek için, bu mantıksal olarak eşdeğer sorguyu denedim:
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
İşte bunun için plan ( plan bağlantısını yapıştırın ):
Tabii ki, plana göre grup akışı toplama operatörü olmadan geçebilir.
Her iki sorgunun dizinin sonundan "geriye" okuduğuna ve maksimum revizyonu almak için "ilk 1" e dikkat edin.
Burada ne eksik? Akış toplamı ilk sorguda gerçekten çalışıyor mu yoksa ortadan kaldırılabiliyor mu (ve optimize edilmeyen bir kısıtlama değil mi)?
Bu arada, bunun inanılmaz derecede pratik bir sorun olmadığını fark ediyorum (her iki sorgu da 0 ms CPU ve geçen süreyi rapor ediyor), sadece burada sergilenen iç / davranışları merak ediyorum.
Yukarıdaki iki sorguyu çalıştırmadan önce çalıştırdığım kurulum kodu:
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