it-swarm.com.de

Ist es bei der Verwendung von GETDATE () an vielen Stellen besser, eine Variable zu verwenden?

Besser, ich meine, verbessert es die Leistung um einen geringfügigen Betrag?

Das heißt, bei jedem Aufruf von GETDATE() wie viel work muss der Server diesen Wert zurückgeben?

Wenn ich GETDATE() an vielen Stellen in einer gespeicherten Prozedur verwende, sollte ich stattdessen eine Variable erstellen, um das Datum der Transaktion zu speichern?

declare @transDate datetime = GETDATE()

Benchmarking-Daten wären fantastisch. 

EDITIch möchte klarstellen: Ich interessiere mich hauptsächlich für die tatsächlichen Leistungsunterschiede zwischen diesen beiden Möglichkeiten und ob es signifikant ist oder nicht. 

32
Shmiddty

[HINWEIS: Wenn Sie diese Antwort ablehnen möchten, hinterlassen Sie bitte einen Kommentar, in dem Sie erklären, warum. Es wurde bereits oft herabgestuft und schließlich hat ypercube (danke) mindestens einen Grund dafür erklärt. Ich kann die Antwort nicht entfernen, da sie akzeptiert wird. Sie können also auch dazu beitragen, sie zu verbessern.]

Gemäß diesem Austausch unter Microsoft wurde GETDATE() in SQL Server 2005 von Konstante innerhalb einer Abfrage auf Nicht-Deterministisch geändert . Rückblickend halte ich das nicht für richtig. Ich denke, es war vor SQL Server 2005 völlig nicht deterministisch und wurde dann in die sogenannte "nicht deterministische Laufzeitkonstante" seit SQL Server 2005 gehackt. Der spätere Ausdruck scheint wirklich "Konstante innerhalb einer Abfrage" zu bedeuten.

(Und GETDATE() ist als eindeutig und stolz nicht deterministisch ohne Qualifikatoren definiert.)

Leider bedeutet nicht deterministisch in SQL Server nicht, dass eine Funktion für jede Zeile ausgewertet wird. SQL Server macht dies wirklich unnötig kompliziert und vieldeutig, da nur sehr wenig Dokumentation zu diesem Thema vorhanden ist.

In der Praxis wird der Funktionsaufruf ausgewertet, wenn die Abfrage ausgeführt wird, und nicht einmal, wenn die Abfrage kompiliert wird, und ihr Wert ändert sich bei jedem Aufruf. In der Praxis wird GETDATE() für jeden Ausdruck, in dem es verwendet wird, nur einmal ausgewertet - zur Ausführungszeit anstatt Kompilierzeit . Microsoft fügt jedoch Rand() und getdate() in eine spezielle Kategorie ein, die als nicht deterministische Laufzeitkonstantenfunktionen bezeichnet wird. Im Gegensatz dazu springt Postgres nicht durch solche Rahmen, sondern ruft nur Funktionen auf, die einen konstanten Wert haben, wenn sie als "stabil" ausgeführt werden.

Trotz des Kommentars von Martin Smith ist die SQL Server-Dokumentation zu diesem Thema einfach nicht explizit - GETDATE() wird sowohl als "nicht deterministische" als auch als "nicht deterministische Laufzeitkonstante" beschrieben, aber dieser Begriff wird nicht wirklich erklärt. Die Stelle, an der ich den Begriff gefunden habe In den nächsten Zeilen der Dokumentation heißt es beispielsweise, keine nicht deterministischen Funktionen in Unterabfragen zu verwenden. Das wäre ein dummer Rat für "nicht deterministische Laufzeitkonstante".

Ich würde vorschlagen, eine Variable mit einer Konstante auch innerhalb einer Abfrage zu verwenden, damit Sie einen konsistenten Wert haben. Dies macht auch die Absicht ganz klar: Sie möchten einen einzelnen Wert in der Abfrage. Innerhalb einer einzelnen Abfrage können Sie Folgendes ausführen:

select . . . 
from (select getdate() as now) params cross join
     . . . 

Tatsächlich ist dies ein Vorschlag, den nur einmal in der Abfrage auswerten sollte , aber es kann Ausnahmen geben. Verwirrung entsteht, weil getdate() in allen verschiedenen Zeilen den gleichen Wert zurückgibt - aber in verschiedenen Spalten unterschiedliche Werte zurückgeben kann. Jeder Ausdruck mit getdate() wird unabhängig ausgewertet. Dies ist offensichtlich, wenn Sie ausführen:

select Rand(), Rand()
from (values (1), (2), (3)) v(x);

Innerhalb einer gespeicherten Prozedur möchten Sie einen einzelnen Wert in einer Variablen haben. Was passiert, wenn die gespeicherte Prozedur nach Mitternacht ausgeführt wird und sich das Datum ändert? Wie wirkt sich das auf die Ergebnisse aus?

Ich vermute, dass die Suche nach Datum und Uhrzeit minimal ist und eine Abfrage einmal pro Ausdruck ausgeführt wird. Dies sollte eigentlich kein Leistungsproblem sein, sondern eher ein Problem der Codekonsistenz.

20
Gordon Linoff

Mein Vorschlag wäre, eine Variable hauptsächlich zu verwenden, da der GetDate()-Wert bei einem lang laufenden Prozess zwischen den Aufrufen unterschiedlich sein kann. 

Wenn Sie nicht nur den Date-Teil von GetDate() verwenden, werden Sie sicher sein, dass Sie immer denselben Wert verwenden.

17
Taryn

Ich habe ein paar gespeicherte Prozeduren mit der Funktion GETDATE () als Variable innerhalb von SP getestet, und ich hatte bei IO Lesevorgängen und Ausführungszeit zugenommen, da der Abfrageoptimierer dies nicht weiß Was ist der Wert, den Sie bedienen müssen? Lesen Sie diese Ausführung gespeicherter Prozeduren mit Parametern, Variablen und Literalen , mit der Angabe, dass Sie die GETDATE () - Funktion in jedem Teil der SP verwenden können, wie @ Gordon Linoff dies erwähnt hat Der Wert ändert sich während der Ausführung nicht oder um zu vermeiden, dass der Wert sich möglicherweise ändert, habe ich auf folgende Weise Parameter erstellt:

CREATE PROC TestGetdate
(
@CurrentDate DATETIME = NULL
)
AS
SET CurrentDate  = GETDATE()

......... und verwenden Sie dann die Parameter so, wie Sie es für richtig halten. Sie werden gute Ergebnisse sehen

Alle Kommentare oder Vorschläge sind willkommen.

1
jthalliens

Ein Grund, eine Variable mit getdate () oder Funktionen wie suser_sname () zu verwenden, ist ein großer Leistungsunterschied, wenn Sie Zeilen einfügen oder wenn Sie GROUP BY ausführen. Sie werden dies bemerken, wenn Sie eine große Anzahl von Zeilen einfügen.

Ich litt dabei selbst unter der Migration von 300 GB Daten in mehrere Tabellen.

1
MarianoC

Ich benutzte

WHERE ActualDateShipped+30 > dbo.Today()

in Kombination mit der Funktion unten. Meine Abfragezeit von 13 Sekunden auf 2 Sekunden gebracht. Keine früheren Antworten in diesem Beitrag haben dieses Problem in SQL 2008/R2 gelöst.

CREATE FUNCTION [dbo].[Today]()

    RETURNS date
    AS
    BEGIN

        DECLARE @today date = getdate()

        RETURN @today
    End
0
pghcpa