Ich habe zwei Tabellen: Details und Summen dieser Details.
Details ( langsame Lösung ):
select
OrderId = r.OrderId
, TotalQty = SUM(r.Quantity)
, TotalGrossConsid = SUM(r.Price * r.Quantity)
from dbo.Order r
group by r.OrderId
Summen ( schnelle Lösung ):
select
t.OrderId
, t.TotalQty
, t.TotalGrossConsid
, t.IsValid
from dbo.OrderTotal t
Manchmal werden Summen ungültig (einige Jobs müssen geänderte Summen neu berechnen, aber es verzögert sich). Wie Sie verstehen, ist die zweite Abfrage schneller und die Anzahl der gültigen Summen ist höher als die der ungültigen. Daher suche ich nach einer kombinierten Abfrage, die gültige Summen aus der zweiten Tabelle (Summen) zurückgibt und mithilfe der ersten langsamen Abfrage dynamisch neu berechnete Summen zurückgibt. Damit ist mein Ziel erreicht: Alle Summen sind gültig und die Reaktionszeit ist schneller als die vollständige Neuberechnung.
Hier ist mein Versuch ( Hybridlösung ):
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)
Ich habe die Fast-Lösung mit der Hybrid-Lösung verglichen und 32% bis 68% (relative Abfragekosten) erhalten. Wenn Sie eine kommentierte Variante sehen können, entspricht dies 1% bis 99% (schade). Ist es möglich, diese Abfrage zu verbessern?
HINZUGEFÜGT
@gbn:
Valid = case when i.OrderId is null then 1 else 0 end
...
dbo.OrderTotal t left join dbo.InvalidOrders i
Ja, ich habe einen Job zum Neuberechnen von Summen und dieser Prozess ist nicht mit Abfrageanforderungen synchronisiert. InvalidOrders-Tabellen sind kleine Tabellen, in denen Datensätze gespeichert werden, um zu wissen, dass Summen ungültig sind (neu zu berechnen).
LÖSUNG
Indizierte Ansichten sind die beste Wahl. Beachten Sie die SQL Server-Edition ( Noexpand-Hinweis für Nicht-Enterprise-Editionen) und erstellen Sie einige Datenbankobjekte ( SET ANSI_NULLS ON, SET QUOTED_IDENTIFIER ON
) neu, um indizierte Ansichten auf der Clientseite zu verwenden.
details
. DiesAntworten:
Ich kann nicht verstehen, warum man nicht im laufenden Betrieb aggregieren kann und warum es so langsam ist.
Ist die "gültige" Idee eine Problemumgehung, um die Verzögerung von OrderTotals oder eines Geschäftsprozesses zu bewältigen?Beide Ideen verwerfen die InvalidOrder-Tabelle, die eine Problemumgehung für eine schlechte Indizierung darstellt.
Erstellen Sie eine berechnete Spalte
Fügen Sie einen Index hinzu
Schau was passiert
Verwenden Sie eine indizierte Ansicht
Sie können die berechnete Spalte auch hier verwenden
quelle
Wenn die Kosten nicht zu hoch wären, könnten Sie die
IsValid
Flagge in dieDetail
Tabelle verschieben und indizieren? Dies würde Ihre Transaktionen verlangsamen, aber die Abfrageleistung verbessern, da auf die (vermutlich) großeDetail
Tabelle in einer großen zugegriffen werden würderange scan
quelle