Kürzlich habe ich Kollegen erklärt, wie wichtig es ist, eine Spalte zu haben, nach der Daten in einer Datenbanktabelle sortiert werden können, wenn dies beispielsweise für chronologisch geordnete Daten erforderlich ist. Dies erwies sich als etwas schwierig, da sie ihre Abfrage einfach scheinbar endlos wiederholen konnten und immer dieselbe Reihe von Zeilen in derselben Reihenfolge zurückgaben.
Ich habe das schon einmal bemerkt und konnte nur darauf bestehen, dass sie mir vertrauen und nicht einfach davon ausgehen, dass sich eine Datenbanktabelle wie eine herkömmliche CSV- oder Excel-Datei verhält.
Beispiel: Ausführen der Abfrage (PostgreSQL)
create table mytable (
id INTEGER PRIMARY KEY,
data TEXT
);
INSERT INTO mytable VALUES
(0, 'a'),
(1, 'b'),
(2, 'c'),
(3, 'd'),
(4, 'e'),
(5, 'f'),
(6, 'g'),
(7, 'h'),
(8, 'i'),
(9, 'j');
erstellt eine Tabelle mit einer klaren konzeptuellen Reihenfolge. Dieselben Daten auf einfachste Weise auszuwählen, wäre:
SELECT * FROM mytable;
Gibt mir immer die folgenden Ergebnisse:
id | data
----+------
0 | a
1 | b
2 | c
3 | d
4 | e
5 | f
6 | g
7 | h
8 | i
9 | j
(10 rows)
Ich kann dies immer und immer wieder tun und es werden mir immer die gleichen Daten in der gleichen Reihenfolge zurückgegeben. Ich weiß jedoch, dass diese implizite Reihenfolge gebrochen werden kann. Ich habe sie bereits zuvor gesehen, insbesondere bei großen Datenmengen, bei denen ein zufälliger Wert bei Auswahl anscheinend an die "falsche" Stelle geworfen wird. Mir ist aber aufgefallen, dass ich nicht weiß, wie das passiert oder wie ich es reproduzieren soll. Ich finde es schwierig, Ergebnisse bei Google zu erhalten, da die Suchanfrage in der Regel nur allgemeine Informationen zum Sortieren von Ergebnismengen enthält.
Meine Fragen lauten also im Wesentlichen:
Wie kann ich nachweislich und konkret nachweisen, dass die Rückgabereihenfolge von Zeilen aus einer Abfrage ohne
ORDER BY
Anweisung nicht zuverlässig ist, indem ich vorzugsweise eine Aufschlüsselung der impliziten Reihenfolge verursache und zeige, auch wenn die betreffende Tabelle nicht aktualisiert oder bearbeitet wird ?Macht es überhaupt einen Unterschied, ob die Daten nur einmal massenweise eingefügt und dann nie wieder aktualisiert werden?
Ich würde eine postgres-basierte Antwort vorziehen, da dies diejenige ist, mit der ich am vertrautesten bin, aber ich bin mehr an der Theorie selbst interessiert.
order by
Klausel zu ihren Abfragen hinzuzufügen . Versuchen sie, im Quellcode-Speicher zu sparen? Tastaturverschleiß? Wie lange dauert es, die gefürchtete Klausel einzugeben?Antworten:
Ich sehe drei Möglichkeiten, um sie zu überzeugen:
Lassen Sie sie dieselbe Abfrage ausführen, jedoch mit einer größeren Tabelle (mehr Zeilen) oder wenn die Tabelle zwischen den Ausführungen aktualisiert wird. Oder es werden neue Zeilen eingefügt und einige alte gelöscht. Oder ein Index wird zwischen den Ausführungen hinzugefügt oder entfernt. Oder der Tisch wird abgesaugt (in Postgres). Oder Indizes werden neu erstellt (in SQL Server). Oder die Tabelle wird von einem Cluster in einen Heap geändert. Oder der Datenbankdienst wird neu gestartet.
Sie können vorschlagen, dass sie beweisen, dass verschiedene Ausführungen dieselbe Reihenfolge zurückgeben. Können sie es beweisen? Können sie eine Reihe von Tests bereitstellen, die belegen, dass eine Abfrage das Ergebnis in derselben Reihenfolge liefert, unabhängig davon, wie oft sie ausgeführt wird?
Stellen Sie die Dokumentation verschiedener DBMS in dieser Angelegenheit bereit. Beispielsweise:
PostgreSQL :
SQL Server :
Oracle :
quelle
ORDER BY
, das die Reihenfolge garantiert, egal wie sich die Tabelle ändern wird ? Warum nicht einen Safe hinzufügen lassen, der nicht schadet?Dies ist wieder die Geschichte mit dem schwarzen Schwan. Wenn Sie noch keine gesehen haben, heißt das nicht, dass sie nicht existieren. Hoffentlich führt dies in Ihrem Fall nicht zu einer weiteren weltweiten Finanzkrise, nur zu einigen unglücklichen Kunden.
In der Postgres- Dokumentation heißt es ausdrücklich:
"Das System" umfasst in diesem Fall den Postgres-Daemon selbst (einschließlich der Implementierung seiner Datenzugriffsmethoden und des Abfrageoptimierers), das zugrunde liegende Betriebssystem, das logische und physische Layout des Datenbankspeichers, möglicherweise sogar CPU-Caches. Da Sie als Datenbankbenutzer keine Kontrolle über diesen Stapel haben, sollten Sie sich nicht darauf verlassen, dass er sich für immer so verhält, wie er sich in dieser Minute verhält.
Ihre Kollegen begehen den hastigen Generalisierungsfehler . Um ihre Aussage zu widerlegen, genügt es zu zeigen, dass ihre Annahme nur einmal falsch ist, zB durch diese dbfiddle .
quelle
Betrachten Sie das folgende Beispiel, in dem wir drei verwandte Tabellen haben. Bestellungen, Benutzer und Bestelldetails. OrderDetails ist mit Fremdschlüsseln an die Orders-Tabelle und die Users-Tabelle gebunden. Dies ist im Wesentlichen eine sehr typische Konfiguration für relationale Datenbanken. wohl der ganze Zweck eines relationalen DBMS.
Hier fragen wir die OrderDetails-Tabelle mit der Benutzer-ID 15 ab:
Die Ausgabe der Abfrage sieht folgendermaßen aus:
Wie Sie sehen, stimmt die Reihenfolge der Zeilenausgabe nicht mit der Reihenfolge der Zeilen in der Tabelle "OrderDetails" überein.
Durch Hinzufügen eines expliziten
ORDER BY
Befehls wird sichergestellt, dass die Zeilen in der gewünschten Reihenfolge an den Client zurückgegeben werden:Wenn Reihenfolge der Zeilen ist zwingend notwendig, und Ihre Ingenieure wissen , dass , um zwingend notwendig ist, sollten sie immer nur wollen eine verwenden
ORDER BY
Aussage, da sie könnte sie ihre Bezeichnung kosten , wenn ein Fehler ist zu falscher Reihenfolge zusammen.Eine zweite, vielleicht noch lehrreiches Beispiel, die mit
OrderDetails
Tabelle von oben, wo wir nicht alle anderen Tabellen verknüpft werden , sondern eine einfache Anforderung sowohl die OrderID und die Benutzer - ID zu finden haben Zeilen übereinstimmt, sehen wir das Problem.Wir erstellen einen Index zur Unterstützung der Abfrage, wie Sie es wahrscheinlich im wirklichen Leben tun würden, wenn die Leistung in irgendeiner Weise wichtig ist (wann nicht?).
Hier ist die Abfrage:
Und die Ergebnisse:
Das Hinzufügen einer
ORDER BY
Klausel stellt sicher, dass wir auch hier die richtige Sortierung erhalten.Diese Modelle sind nur einfache Beispiele, bei denen Zeilen ohne explizite
ORDER BY
Anweisung nicht garantiert "in Ordnung" sind . Es gibt noch viele weitere Beispiele, und da sich der Code der DBMS-Engine häufig ändert, kann sich das spezifische Verhalten im Laufe der Zeit ändern.quelle
Als praktisches Beispiel ändert sich in Postgres derzeit die Reihenfolge, wenn Sie eine Zeile aktualisieren:
Ich denke nicht, dass die Regeln dieser bestehenden impliziten Reihenfolge irgendwo dokumentiert sind, definitiv ohne Vorankündigung geändert werden können und definitiv kein portables Verhalten zwischen DB-Engines ist.
quelle
Nicht gerade eine Demo, aber zu lang für einen Kommentar.
Bei großen Tabellen führen einige Datenbanken verschachtelte parallele Überprüfungen durch:
Wenn zwei Abfragen dieselbe Tabelle durchsuchen möchten und fast zur selben Zeit eintreffen, befindet sich die erste möglicherweise auf dem Weg durch die Tabelle, wenn die zweite gestartet wird.
Die zweite Abfrage kann Datensätze ab der Tabellenmitte empfangen (wenn die erste Abfrage abgeschlossen ist) und die Datensätze dann ab dem Tabellenanfang empfangen.
quelle
Erstellen Sie einen gruppierten Index mit der "falschen" Reihenfolge. Beispiel: Cluster ein
ID DESC
. Dies gibt häufig die umgekehrte Reihenfolge aus (obwohl dies auch nicht garantiert ist).quelle