Weil ich gerade meine TSQL-Fortgeschrittenen-Schulung auf SQL-PASS-Tauglichkeit checke, kam mir der Artikel über die Performance von Common-Table-Expressions (CTE) gerade recht. Meine eigenen Recherchen ergaben auch, dass bei echt rekursiven Abfragen die Performance der CTEs mit zunehmender Datenmenge gegenüber einer "ausgeschriebenen" Lösung (mittels UNION) verliert. Das hatte ich so nicht erwartet, vor allem, wenn man sich die Zugriffspläne zum Vergleich anschaut. Aber wenn man statt dessen auf den nötigen I/O schaut, dann wird die Ursache schnell klar.
Daher ist das meine heute Lese-Empfehlung.
Hallo Thomas,
vielleicht kannst/magst du das hier verwenden (s. insb. letzten Eintrag!):
Fortlaufende Summe bei Kassabuch
http://social.msdn.microsoft.com/Forums/de-DE/sqlserverde/thread/498c25e0-5180-4039-9e77-e5a5dc1ee34e
Mag sein, das sowas in der Art schon woanders beschrieben wurde, ich bin aber selbst drauf gekommen 🙂
Viele Grüße
Christoph
Hallo Christoph,
meinen Glückwunsch. Diese Lösung sah ich so noch nirgends. Bei meinen ersten Tests war die CTE aber nicht so wirklich schnell. Ich schaue mir das aber noch mal in Ruhe an, möglicherweise muss ich noch etwas tunen.
Ich erinnere mich dunkel an eine Artikelserien von Itzik Ben-Gan zu dem Thema "running total". Leider sind die Artikel nicht frei verfügbar. Hier steht der mit einer CLR-Lösung und hier mit Set-Based vs. Cursor-Based Solutions for Running Aggregates.
Interessant ist auch der Trick von Robin Hames mit dem Update-Befehl. Aber ich hörte auch schon Bedenken, dass das bei einem parallelisierten Ausführungsplan nicht funzt. Mit Deinen Beispieldaten hat er bei mir auch bei 250000 Datensätzen nicht parallelisiert und war sehr schnell fertig:
DECLARE @kb TABLE
(id INT PRIMARY KEY CLUSTERED, debit MONEY, credit MONEY, summe MONEY);
DECLARE @Summe money;
SET @Summe = 0;
INSERT INTO @kb (id, debit, credit, summe)
SELECT id, debit, credit, NULL
FROM #kb
WHERE id <250000
ORDER BY id;
UPDATE @kb
SET @Summe = summe = @Summe + debit - credit
FROM @kb;
SELECT * FROM @kb;
Viele Grüße
Thomas
Hallo Thomas,
der Anwendungsfall macht ja nur Sinn, wenn der Anwender sich die Daten anschaut. Und die Datenmenge ist dadurch begrenzt (ab wieviel Datensätzen wird man wahnsinnig!? 😉 ). Mit Paging, bei dem man die Summen der davorliegenden Seiten zuerst ermittelt und nur für die aktuell sichtbare Seite die fortlaufenden Summen anzeigt, dürfte das kein Problem sein.
Und wenn ich die Summe bis Buchung 76532 sehen möchte, brauche ich mir die vorherigen Summen auch nicht anschauen.
Viele Grüße
Christoph