Перевірте цей запит. Це досить просто (див. У кінці публікації визначення таблиць та індексів та сценарій репро).
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Зауважте: "І 1 = (ВИБІР 1) - це просто уникнути автоматичного параметризації цього запиту, що, як мені здається, заплутало проблему - він насправді отримує той самий план із цим пунктом або без нього, хоча
А ось план ( вставте посилання на план) :
Оскільки там є "топ-1", я здивувався, побачивши оператора потокового агрегату. Мені це не здається необхідним, оскільки гарантовано буде лише один ряд.
Щоб перевірити цю теорію, я спробував цей логічно еквівалентний запит:
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
Ось план для цього ( вставте посилання на план ):
Звичайно, група за планом може обійтись без оператора агрегату потоку.
Зауважте, що обидва запити читають "назад" з кінця індексу та роблять "верхню 1", щоб отримати максимальну редакцію.
Що я тут пропускаю? Чи поточний агрегат справді працює в першому запиті, чи його можна буде усунути (і це лише обмеження оптимізатора, що це не так)?
До речі, я розумію, що це не є надзвичайно практичною проблемою (обидва запити повідомляють 0 мс процесора та минув час), мені просто цікаво про те, що тут проявляються внутрішні / поведінки.
Ось код налаштування, який я запускав перед тим, як запустити два вищевказані запити:
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