Confira esta consulta. É bem simples (veja o final do post para definições de tabela e índice e um script de reprodução):
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Nota: o "AND 1 = (SELECT 1) é apenas para evitar que essa consulta seja parametrizada automaticamente, o que eu senti que estava confundindo o problema - na verdade, ele obtém o mesmo plano com ou sem essa cláusula
E aqui está o plano ( cole o link do plano) :
Como há um "top 1" lá, fiquei surpreso ao ver o operador de agregação de fluxo. Não me parece necessário, pois é garantido que haverá apenas uma linha.
Para testar essa teoria, experimentei esta consulta logicamente equivalente:
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
Aqui está o plano para esse ( cole o link do plano ):
Com certeza, o grupo por plano é capaz de sobreviver sem o operador de agregação de fluxo.
Observe que ambas as consultas lêem "para trás" do final do índice e fazem um "top 1" para obter a revisão máxima.
O que estou perdendo aqui? A agregação de fluxo está realmente funcionando na primeira consulta ou deve ser eliminada (e é apenas uma limitação do otimizador que não é)?
A propósito, percebo que este não é um problema incrivelmente prático (ambas as consultas relatam 0 ms de CPU e tempo decorrido), estou apenas curioso sobre os internos / comportamento exibidos aqui.
Aqui está o código de configuração que executei antes de executar as duas consultas acima:
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
Você pode ver a função desse agregado se nenhuma linha corresponder à
WHERE
cláusula.Nesse caso, zero linhas vão para o agregado, mas ainda emite uma, pois a semântica correta deve retornar
NULL
neste caso.Este é um agregado escalar em oposição a um vetor.
Sua consulta "logicamente equivalente" não é equivalente. A adição
GROUP BY Id
o tornaria um agregado vetorial e, em seguida, o comportamento correto seria não retornar nenhuma linha.Veja Diversão com Agregados Escalares e Vetoriais para saber mais sobre isso.