Nichtdeterministisches Verhalten
Mehrere Operatoren in DuckDB zeigen nichtdeterministisches Verhalten. Vor allem verwendet SQL Mengensemantik, wodurch Ergebnisse in unterschiedlicher Reihenfolge zurückgegeben werden dürfen. DuckDB nutzt das zur Leistungssteigerung, insbesondere bei mehrfädiger Query-Ausführung. Andere Faktoren wie unterschiedliche Compiler, Betriebssysteme und Hardwarearchitekturen können die Reihenfolge ebenfalls ändern. Diese Seite dokumentiert die Fälle, in denen Nichtdeterminismus erwartetes Verhalten ist. Wenn Sie Ihre Queries deterministisch machen möchten, siehe den Abschnitt „Mit Nichtdeterminismus umgehen“.
Mengensemantik
Eine der häufigsten Quellen von Nichtdeterminismus ist die von SQL verwendete Mengensemantik. Wenn Sie beispielsweise die folgende Query wiederholt ausführen, können Sie zwei unterschiedliche Ergebnisse erhalten:
SELECT *FROM ( SELECT 'A' AS x UNION SELECT 'B' AS x);Beide Ergebnisse A, B und B, A sind korrekt.
Unterschiedliche Ergebnisse auf unterschiedlichen Plattformen: array_distinct
Die Funktion array_distinct kann auf unterschiedlichen Plattformen Ergebnisse in unterschiedlicher Reihenfolge zurückgeben:
SELECT array_distinct(['A', 'A', 'B', NULL, NULL]) AS arr;Für diese Query sind sowohl [A, B] als auch [B, A] gültige Ergebnisse.
Gleitkomma-Aggregationen mit Multithreading
Ungenauigkeiten bei Gleitkommazahlen können bei mehrfädiger Ausführung unterschiedliche Ergebnisse liefern:
Beispielsweise können stddev und corr nichtdeterministische Ergebnisse liefern:
CREATE TABLE tbl AS SELECT 'ABCDEFG'[floor(random() * 7 + 1)::INT] AS s, 3.7 AS x, i AS y FROM range(1, 1_000_000) r(i);
SELECT s, stddev(x) AS standard_deviation, corr(x, y) AS correlationFROM tblGROUP BY sORDER BY s;Die erwarteten Standardabweichungen und Korrelationen dieser Query sind 0 für alle Werte von s.
Bei Ausführung auf mehreren Threads kann die Query jedoch aufgrund von Gleitkommaungenauigkeiten kleine Zahlen (0 <= z < 10e-16) zurückgeben.
Mit Nichtdeterminismus umgehen
Für die meisten Anwendungsfälle verursacht Nichtdeterminismus keine Probleme. Es gibt jedoch Fälle, in denen deterministische Ergebnisse erwünscht sind. Versuchen Sie dann die folgenden Workarounds:
-
Begrenzen Sie die Anzahl der Threads, um durch Multithreading eingeführten Nichtdeterminismus zu vermeiden.
SET threads = 1; -
Erzwingen Sie eine Ordnung. Sie können beispielsweise die Klausel
ORDER BY ALLverwenden:SELECT *FROM (SELECT 'A' AS xUNIONSELECT 'B' AS x)ORDER BY ALL;Sie können Listen auch mit
list_sortsortieren:SELECT list_sort(array_distinct(['A', 'A', 'B', NULL, NULL])) AS iORDER BY i;Es ist auch möglich, ein deterministisches Shuffling einzuführen.