Dadas as duas tabelas a seguir:
CREATE TABLE SalesLedger (
Id int PRIMARY KEY IDENTITY,
Date date NOT NULL,
Total decimal(38,18),
INDEX IX (Date, Total)
);
CREATE TABLE Purchases (
Id int PRIMARY KEY IDENTITY,
Date date NOT NULL,
Total decimal(38,18),
INDEX IX (Date, Total)
);
E a seguinte visão
CREATE VIEW ViewMetrics
AS
Select
Date,
'Sale' as Metric,
Total as Value
From SalesLedger
UNION ALL
Select
Date,
'Purchase' as Metric,
Total as Value
From Purchases;
A consulta a seguir usa um Concatenation
Sort
par:
Select SUM(Value) as Sales, Date
from ViewMetrics
Group By Date;
Considerando que uma pequena reescrita dá obviamente mais desempenhoMerge Concatenation
SELECT SUM(Sales), Date
FROM (
Select SUM(Value) as Sales, Date
from ViewMetrics
Group By Metric, Date
) t
GROUP BY Date;
O compilador pode ver claramente que a visualização está particionada por Metric
, como mostra esta consulta, não Sort
é necessário:
Select SUM(Value) as Sales, Date
from ViewMetrics
where Metric = 'Sale'
Group By Date;
A questão é: por que a primeira consulta força a Sort
, enquanto a segunda pode usar uma mais eficiente Merge Concatenation
, visto que a Metric
coluna não possui WHERE
predicado em nenhum dos casos?
O compilador não deveria ser capaz de ver que a Merge
funcionaria, visto que os índices já estão classificados Date
e o particionamento está ativado Metric
? Ou se não consegue ver isso, por que GROUP BY Metric, Date
de repente lhe dá essa habilidade?
Ainda mais estranho, como descobriu @MartinSmith, se não houver dados, o compilador usará o plano melhor, embora sem uma agregação intermediária em Metric, Date
. db<>fiddle Por outro lado, a mesclagem sem agregação parcial é provavelmente mais lenta do que a classificação após a agregação parcial, porque há mais linhas para mesclar. A questão é por que não é possível fazer agregação parcial e mesclar ao mesmo tempo por padrão?
Suponho que haja alguma otimização específica para uma visualização particionada quando a agregação inclui o particionamento, porque nesse caso ela usa uma concatenação e quando uma ordem é necessária, ela usa a concatenação de mesclagem, consulte db<> fiddle . Isso ajuda quando você deseja agregar ainda mais, pois os dados agora já estão classificados na ordem correta. Mas se você não fizer a agregação intermediária não tem lógica que a aplique.