Tenho duas tabelas: detalhes e totais desses detalhes.
Detalhes ( solução lenta ):
select
OrderId = r.OrderId
, TotalQty = SUM(r.Quantity)
, TotalGrossConsid = SUM(r.Price * r.Quantity)
from dbo.Order r
group by r.OrderId
Totais ( solução rápida ):
select
t.OrderId
, t.TotalQty
, t.TotalGrossConsid
, t.IsValid
from dbo.OrderTotal t
Às vezes, os totais se tornam inválidos (algum trabalho precisa recalcular os totais alterados, mas atrasa). Como você entende, a segunda consulta é mais rápida e o número de totais válidos é maior que os inválidos. Portanto, estou procurando uma consulta combinada que retorne totais válidos da segunda tabela (totais) e retorne totais recalculados dinamicamente usando a primeira consulta lenta. Portanto, meu objetivo será alcançado: todos os totais são válidos e o tempo de resposta é mais rápido do que o recálculo completo.
Aqui está minha tentativa ( solução híbrida ):
with fast_static(OrderId, TotalQty, TotalGrossConsid, IsValid)
as
(
select
t.OrderId
, t.TotalQty
, t.TotalGrossConsid
, t.IsValid
from dbo.OrderTotal t
)
, slow_dynamic(OrderId, TotalQty, TotalGrossConsid)
(
select
OrderId = r.OrderId
, TotalQty = SUM(r.Quantity)
, TotalGrossConsid = SUM(r.Price * r.Quantity)
from dbo.Order r
)
select
OrderId, TotalQty, TotalGrossConsid
from fast_static
where IsValid = 1
union all
select
OrderId, TotalQty, TotalGrossConsid
from slow_dynamic s
--inner join fast_static ff
--on ff.OrderId = s.OrderId
where --ff.Valid = 0 -- too slow!!!
s.OrderId in (select OrderId from fast_static f where f.Valid = 0)
Comparei a solução Fast com a Híbrida, obtive 32% a 68% (custos relativos de consulta). Se você pode ver a variante comentada, é igual a 1% a 99% (que pena). É possível melhorar esta consulta?
ADICIONADO
@gbn:
Valid = case when i.OrderId is null then 1 else 0 end
...
dbo.OrderTotal t left join dbo.InvalidOrders i
Sim, tenho um trabalho para recalcular totais e este processo não está sincronizado com os pedidos de consulta. As tabelas InvalidOrders são pequenas que armazenam registros para saber que os totais são inválidos (a serem recalculados)
SOLUÇÃO
Visualizações indexadas são a melhor escolha. Esteja ciente da edição do SQL Server ( dica noexpand para edições não corporativas) e esteja pronto para recriar alguns objetos de banco de dados ( SET ANSI_NULLS ON, SET QUOTED_IDENTIFIER ON
) para começar a usar exibições indexadas no lado do cliente.
Não consigo entender por que você não pode agregar na hora e por que é tão lento.
A ideia "Válida" é uma solução alternativa para lidar com o atraso de OrderTotals ou algum processo de negóciosAmbas as ideias descartam a tabela InvalidOrder, que é uma solução alternativa para uma indexação ruim.
Criar uma coluna computada
Adicionar um índice
Veja o que acontece
Use uma exibição indexada
Você pode usar a coluna calculada aqui também
Se o custo não fosse muito alto, você poderia considerar mover o
IsValid
sinalizador para aDetail
tabela e indexá-lo? Isso retardaria suas transações, mas melhoraria o desempenho da consulta, pois a tabela (presumivelmente) grandeDetail
seria acessada em um granderange scan