Wenn Sie eine Unterabfrage verwenden, um die Gesamtanzahl aller vorherigen Datensätze mit einem übereinstimmenden Feld zu ermitteln, ist die Leistung in einer Tabelle mit nur 50.000 Datensätzen schlecht. Ohne die Unterabfrage wird die Abfrage in wenigen Millisekunden ausgeführt. Bei der Unterabfrage beträgt die Ausführungszeit mehr als eine Minute.
Für diese Abfrage muss das Ergebnis:
- Schließen Sie nur diese Datensätze innerhalb eines bestimmten Datumsbereichs ein.
- Fügen Sie eine Anzahl aller vorherigen Datensätze hinzu, ohne den aktuellen Datensatz, unabhängig vom Datumsbereich.
Grundlegendes Tabellenschema
Activity
======================
Id int Identifier
Address varchar(25)
ActionDate datetime2
Process varchar(50)
-- 7 other columns
Beispieldaten
Id Address ActionDate (Time part excluded for simplicity)
===========================
99 000 2017-05-30
98 111 2017-05-30
97 000 2017-05-29
96 000 2017-05-28
95 111 2017-05-19
94 222 2017-05-30
erwartete Ergebnisse
Für den Datumsbereich von 2017-05-29
bis2017-05-30
Id Address ActionDate PriorCount
=========================================
99 000 2017-05-30 2 (3 total, 2 prior to ActionDate)
98 111 2017-05-30 1 (2 total, 1 prior to ActionDate)
94 222 2017-05-30 0 (1 total, 0 prior to ActionDate)
97 000 2017-05-29 1 (3 total, 1 prior to ActionDate)
Die Datensätze 96 und 95 werden vom Ergebnis ausgeschlossen, sind jedoch in der PriorCount
Unterabfrage enthalten
Aktuelle Abfrage
select
*.a
, ( select count(*)
from Activity
where
Activity.Address = a.Address
and Activity.ActionDate < a.ActionDate
) as PriorCount
from Activity a
where a.ActionDate between '2017-05-29' and '2017-05-30'
order by a.ActionDate desc
Aktueller Index
CREATE NONCLUSTERED INDEX [IDX_my_nme] ON [dbo].[Activity]
(
[ActionDate] ASC
)
INCLUDE ([Address]) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
Frage
- Welche Strategien könnten verwendet werden, um die Leistung dieser Abfrage zu verbessern?
Bearbeiten 1
Als Antwort auf die Frage, was ich an der DB ändern kann: Ich kann die Indizes ändern, nur nicht die Tabellenstruktur.
Bearbeiten 2
Ich habe jetzt einen Basisindex für die Address
Spalte hinzugefügt , aber das schien sich nicht wesentlich zu verbessern. Momentan finde ich eine viel bessere Leistung, wenn ich eine temporäre Tabelle erstelle und die Werte ohne die einfüge PriorCount
und dann jede Zeile mit ihrer spezifischen Anzahl aktualisiere.
Edit 3
Die gefundene Index-Spool Joe Obbish (akzeptierte Antwort) war das Problem. Sobald ich eine neue hinzufügte nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, sanken die Abfragezeiten von einer Minute auf weniger als eine Sekunde, ohne eine temporäre Tabelle zu verwenden (siehe Bearbeiten 2).
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, sanken die Abfragezeiten von einer Minute auf weniger als eine Sekunde. +10 wenn ich könnte. Vielen Dank!