Mira esta consulta. Es bastante simple (vea el final de la publicación para las definiciones de tabla e índice, y un script de repro):
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Nota: el "Y 1 = (SELECCIONAR 1) es solo para evitar que esta consulta se parametrice automáticamente, lo que sentí que confundía el problema, aunque en realidad obtiene el mismo plan con o sin esa cláusula
Y aquí está el plan ( pegue el enlace del plan) :
Como hay un "top 1" allí, me sorprendió ver el operador agregado de flujo. No me parece necesario, ya que se garantiza que solo habrá una fila.
Para probar esa teoría, probé esta consulta lógicamente equivalente:
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
Aquí está el plan para ese ( pegue el enlace del plan ):
Efectivamente, el grupo por plan puede sobrevivir sin el operador agregado de flujo.
Observe que ambas consultas leen "hacia atrás" desde el final del índice y hacen un "top 1" para obtener la revisión máxima.
¿Que me estoy perdiendo aqui? ¿El agregado de flujo realmente está funcionando en la primera consulta, o debería poder eliminarse (y es solo una limitación del optimizador que no lo es)?
Por cierto, me doy cuenta de que este no es un problema increíblemente práctico (ambas consultas informan 0 ms de CPU y tiempo transcurrido), solo tengo curiosidad acerca de los aspectos internos / comportamiento que se exhiben aquí.
Aquí está el código de configuración que ejecuté antes de ejecutar las dos consultas anteriores:
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