Großer Leistungsunterschiede (1 Std und 1 Minute) in SQL. Kannst du erklären warum?
-
10-07-2019 - |
Frage
Die folgenden Fragen dauern 70 Minuten bzw. 1 Minute auf einer Standardmaschine für 1 Million Rekorde. Was könnten die möglichen Gründe sein?
Abfrage [01:10:00
SELECT *
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
ELSE sys.fn_cdc_increment_lsn(0x00) END
, sys.fn_cdc_get_max_lsn()
, 'all with mask')
WHERE __$operation <> 1
Modifizierte Abfrage [00:01:10
DECLARE @MinLSN binary(10)
DECLARE @MaxLSN binary(10)
SELECT @MaxLSN= sys.fn_cdc_get_max_lsn()
SELECT @MinLSN=CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')
ELSE sys.fn_cdc_increment_lsn(0x00) END
SELECT *
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
@MinLSN, @MaxLSN, 'all with mask') WHERE __$operation <> 1
Geändert
Ich habe versucht, das Szenario mit einer ähnlichen Funktion neu zu erstellen, um festzustellen, ob die Parameter für jede Zeile ausgewertet werden.
CREATE FUNCTION Fn_Test(@a decimal)RETURNS TABLE
AS
RETURN
(
SELECT @a Parameter, Getdate() Dt, PartitionTest.*
FROM PartitionTest
);
SELECT * FROM Fn_Test(RAND(DATEPART(s,GETDATE())))
Aber ich erhalte den gleichen Wert für den Spalten -Parameter "Parameter" für AA -Millionen -Datensätze, die in 38 Sekunden verarbeitet wurden.
Lösung
Selbst deterministische Skalarfunktionen werden mindestens einmal pro Zeile bewertet. Wenn die gleiche deterministische Skalarfunktion in derselben "Zeile" mit denselben Parametern mehrmals auftritt, werde ich jedoch nur noch einmal bewertet - z. B. in einem CASE WHEN fn_X(a, b, c) > 0 THEN fn_X(a, b, c) ELSE 0 END
oder sowas ähnliches.
Ich denke, Ihr Rand -Problem ist, dass Sie weiterhin neu säumen:
Wiederholte Anrufe von Rand () mit demselben Saatgutwert geben dieselben Ergebnisse zurück.
Wenn Rand () mit einem angegebenen Saatgutwert aufgerufen wird, ergeben alle nachfolgenden Aufrufe von Rand () Ergebnisse basierend auf dem gesetzten Rand () -Auf. Beispielsweise gibt die folgende Abfrage immer die gleiche Abfolge von Zahlen zurück.
Ich habe die Skalarfunktionsergebnisse zwischengespeichert, wie Sie angedeutet haben - selbst wenn Sie Tabellen der skalaren Funktionsergebnisse vorhanden und sich ihnen anschließen. Es muss irgendwann etwas getan werden, um skalare Funktionen zu erfüllen. Richtig, nicht, die beste Option ist die CLR - anscheinend übertreffen diese bei weitem SQL UDFs. Leider kann ich sie in meiner aktuellen Umgebung nicht verwenden.
Andere Tipps
In Ihrer ersten Abfrage Ihre fn_cdc_increment_lsn
und fn_cdc_get_min_lsn
Werden Sie für jede Zeile ausgeführt. Im zweiten Beispiel nur einmal.