AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken C# SQL Server: Performance von DATEADD ist ne katastrophe
Thema durchsuchen
Ansicht
Themen-Optionen

SQL Server: Performance von DATEADD ist ne katastrophe

Ein Thema von Phoenix · begonnen am 22. Okt 2008 · letzter Beitrag vom 24. Okt 2008
Antwort Antwort
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.641 Beiträge
 
#1

SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 22. Okt 2008, 10:54
Datenbank: SQL Server • Version: 2005 • Zugriff über: TSQL
Hi,

hier benutzen wir die DATEADD-Funktion, um rekursiv über eine Tabelle Werte zur Laufzeit zu berechnen.
Nur leider ist das ausführungstechnisch ne Katastrophe.

Allein der DATEADD-Aufruf in der rekursiv aufgerufenen Funktion macht bei einem Query einen Unterschied zwischen 0,x und ca. 6-8 Sekunden Laufzeit aus. Und es wurde tatsächlich nur der eine Aufruf auskommentiert, das heisst die Rekursionstiefe der Funktion wird jedes mal erreicht - die ist also nicht schuld.

Kann man DATEADD irgendwie anders / performanter im SQL Server implementieren?
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#2

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 22. Okt 2008, 11:15
Hallo,

der Unterschied zwischen
SQL-Code:
select
--DateAdd(YY,5,Datum),
Datum from tabelle
und
SQL-Code:
select
DateAdd(YY,5,Datum),
Datum from tabelle
liegt bei unserer Datenbank bei ca. 250000 Sätzen unter 1 Sekunde.
Mit was für Datenmengen arbeitet Ihr. Führt Ihr das SQL pro Datensatz aus, sind die zu ändernden Felder in einem Index, der mitgepflegt werden muss? Gibt es Trigger, die auf die Änderung des Datumsfeldes reagieren?
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.641 Beiträge
 
#3

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 22. Okt 2008, 11:56
Hrm.. etwas nähere Investigation hat ergeben, dass es an was anderen liegt. Was, ist allerdings nicht wirklich raus.
Das wird in einer UDF aufgerufen, die rekursiv Parent-Beziehungen hinaufgeht und von einem Startdatensatz aus Werte weiterkalkuliert. Nehmen wir die Kalkulation heraus, ist das Ding sofort fertig - und die Kalkulation besteht aus
SET @newValue = DATEADD(day, @offset, @oldValue) Interessanterweise ist es aber so, dass er genau dann schnell ist, wenn er in der Rekursion im Startwert NULL zurück bekommt und aufgrund dieses Wertes dann eben nicht in die Berechnung läuft, bei einem anderen Wert ist er aber langsam.

Als ob der SQL Server in dem Moment, in dem er den Startwert = NULL ermittelt hat, die weitere Berechnung wegoptimieren und gleich alle Ergebnisse mit NULL besetzen würde, anstelle jedem nochmal einen zusätzlichen Wert (und sei es anstelle von Dateadd ein Konstanter Zeitwert) zuweisen müsste.

Ergo: Weise ich einen Wert zu (egal ob Berechnet oder Konstant), braucht die SP ~7 Sekunden. Weise ich keinen Wert zu, ist es in unter 1 Sekunde abgehandelt. Vorausgesetzt, der Rekursiv ermittelte Startwert ist nicht NULL. Ist er NULL, ist er in beiden Fällen in unter 1 Sekunde durch.

Die Rekursion muss er aber in beiden Fällen vollends auflösen, deswegen wundert es mich, dass dann die reine Zuweisung von egal was an den Ausgangswert so einen derben Einfluss auf die Geschwindigkeit hat.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 22. Okt 2008, 20:33
Kannst du mal näher auf die Rekursion eingehen. Ist die überhaupt nötig? Vielleicht kann man da ja etwas anders machen.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#5

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 22. Okt 2008, 20:46
Ich möchte nochmal etwas zur Performance der DATEADD-Funktion beitragen:
SQL-Code:
select count (distinct datum) from Tabelle
select count (distinct DateAdd(yy,5,datum)) from Tabelle
Ergibt beim Query-Plan ein Verhältnis von 1:5 (13% zu 87%), letzteres ist also 5x langsamer.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.641 Beiträge
 
#6

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 23. Okt 2008, 09:41
Zitat von omata:
Kannst du mal näher auf die Rekursion eingehen. Ist die überhaupt nötig? Vielleicht kann man da ja etwas anders machen.
Mal schauen.
In einer Tabelle stehen Informationen zu dieser Vorwärtskalkulation (pro einzelnem Datensatz) von Daten (Muss berechnet werden? Wenn ja: von welchem Wert (anderer Datensatz) aus? Wieviel und was (Tage, Wochen, Monate, Jahre?).

In einer weiteren Tabelle stehen dann die Werte.

Für die Berechnung geht die Funktion dann her, selektiert zu dem abgefragten Datensatz den Info-Satz (Tabelle 1).
Wenn nicht kalkuliert wird, wird der eigentliche Wert in der Tabelle zurück gegeben.
Wenn kalkuliert wird, wird die selbe Funktion für den Parent aufgerufen (um ggf. den kalkulierten Wert des Parents zu ermitteln), und dann wird der so ermittelte Wert mit der entsprechenden Anzahl an Tagen / Wochen / etc. aufaddiert und zurück gegeben.

Wir haben in einem Beispiel 30 Datensätze, die jeweils vom Vordermann abhängig sind.
Das heisst also 30! Aufrufe. Da es drei solche Datumswerte gibt kann das also bis zu 3* 30! calls geben. Im Test haben wir zwei Reihen kalkulieren lassen.

Und jetzt kommt eben der Knackpunkt:
Die Anzahl der Aufrufe ist Konstant - wenn der erste Datensatz leer ist, dann gibt es nichts zu kalkulieren, und die View ist in unter 1 sekunde da. Ist der erste Wert in einer Berechnung belegt, braucht das ganze 6 - 7 Sekunden. Sind beide belegt entsprechend 12 - 15 Sekunden.

Interessant ist nun, dass der Aufwand für beide alternativen (es kommt beim Aufruf der Funktion 0 oder ein anderer Wert zurück) eigentlich im Test der gleiche ist. Kommt 0 zurück, weisen wir den Wert der Ausgabe zu, der aktuell im abgefragten Datensatz steht. Kommt ein DateTime Wert <> 0 zurück, so weisen wir diesen Wert der Ausgabe zu. (Das DateAdd wurde auskommentiert).

Dennoch ist dieser massive Unterschied in der Laufzeit da. Ich verstehe das einfach nicht. Es sollte dem SQL Server doch eigentlich egal sein, was da zugewiesen wird, oder?
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 23. Okt 2008, 23:54
Ich bin nicht sicher, ob ich deine Beschreibung richtig verstanden habe. Trotzdem versuche ich mal einen Vorschlag zu machen. Vielleicht bringt er dich ja auf einen anderen Ansatz...

Tabellenstruktur...
SQL-Code:
CREATE TABLE [Daten] (
   [id] [int] NOT NULL ,
   [parent_id] [int] NULL ,
   [Datum] [datetime] NULL ,
   CONSTRAINT [PK_Daten] PRIMARY KEY CLUSTERED
   (
      [id]
   ) ON [PRIMARY] ,
   CONSTRAINT [FK_Daten_Daten] FOREIGN KEY
   (
      [parent_id]
   ) REFERENCES [Daten] (
      [id]
   )
) ON [PRIMARY]
Tabelleninhalt...
Code:
id  parent_id   datum
1    NULL        21.10.2000
2    1            NULL
3    2            NULL
4    NULL        01.01.2008
5    4            NULL
6    3            30.11.2000
Abfrage...
SQL-Code:
DECLARE @id INT
SET @id = NULL -- NULL = alle letzten Datensätze
               -- Zahl = Nur den ausgewählten Datensatz

DECLARE @IDS TABLE (id INT PRIMARY KEY, parent_id INT, Datum1 DATETIME, Datum2 DATETIME)
DECLARE @Done BIT

SET @Done = 0

INSERT @IDS(id, parent_id, Datum1, Datum2)
SELECT id, parent_id, NULL, Datum
FROM daten x
WHERE ( NOT EXISTS (SELECT *
                      FROM daten
                      WHERE parent_id = x.id)
       AND @id IS NULL)
  OR (id = @id AND @id IS NOT NULL)

IF @@ROWCOUNT = 0 SET @Done = 1
WHILE @Done = 0 BEGIN

  UPDATE @IDS
  SET parent_id = d.parent_id,
      datum1 = d.datum
  FROM @IDS ids
  INNER JOIN daten d
    ON ids.parent_id = d.id
  WHERE ids.datum1 IS NULL
    AND ids.parent_id IS NOT NULL

  IF @@ROWCOUNT = 0 SET @Done = 1
END

SELECT id, datum1, datum2,
       COALESCE(DATEDIFF(dd, datum1, datum2), 0) tage,
       COALESCE(DATEDIFF(wk, datum1, datum2), 0) wochen,
       COALESCE(DATEDIFF(mm, datum1, datum2), 0) monate,
       COALESCE(DATEDIFF(yy, datum1, datum2), 0) jahre
FROM @IDS
Vielleicht kannst du ja auch nochmal genauer und mit Beispieldaten zeigen was du hast und was du benötigst.
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.641 Beiträge
 
#8

Re: SQL Server: Performance von DATEADD ist ne katastrophe

  Alt 24. Okt 2008, 00:24
Danke, das muss ich mir mal in einer ruhigen Minute zu Gemüte führen. Im Moment blick ich grad ned durch, das sollte morgen wenn ich ausgeschlafen bin aber anders aussehen

Ich darf leider nicht weiter auf die Datenstruktur und/oder die Daten eingehen. Allerdings ist der aktuelle Stand jetzt eher, dass wir nach Änderungen an Daten, die auf diese Datumskalkulation einfluss haben, die Daten gleich live in einem Trigger vorberechnen und dann zu den regulären Datensätzen speichern, anstelle sie jedes mal beim auslesen neu zu berechnen. Das ist natürlich ein grösserer Aufwand beim Speichern, aber den auch nur einmal von der geänderten Stelle aus alle Pfade 'nach unten' anstelle jedes mal von unten nach oben hochzukalkulieren und dabei ggf. etliche Werte noch doppelt zu berechnen.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz