Zum Inhalt springen

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 correlation
FROM tbl
GROUP BY s
ORDER 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:

  1. Begrenzen Sie die Anzahl der Threads, um durch Multithreading eingeführten Nichtdeterminismus zu vermeiden.

    SET threads = 1;
  2. Erzwingen Sie eine Ordnung. Sie können beispielsweise die Klausel ORDER BY ALL verwenden:

    SELECT *
    FROM (
    SELECT 'A' AS x
    UNION
    SELECT 'B' AS x
    )
    ORDER BY ALL;

    Sie können Listen auch mit list_sort sortieren:

    SELECT list_sort(array_distinct(['A', 'A', 'B', NULL, NULL])) AS i
    ORDER BY i;

    Es ist auch möglich, ein deterministisches Shuffling einzuführen.