PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie sorgen dafür, dass Daten nicht sortiert werden?

Es ist wichtig zu verstehen, dass SQL-Tabellen keine Reihenfolge haben . Die Reihenfolge der Zeilen, die Sie sehen, wenn Sie SELECT ohne ORDER BY bleibt nur gleich, weil es für die Datenbank schneller ist, sie in dieser Reihenfolge zu erhalten als in einer anderen Reihenfolge. PostgreSQL gibt nur Zeilen in dieser Reihenfolge zurück, wenn Sie einen sequentiellen Scan der Tabelle durchführen; Wenn es einen Index für die Abfrage verwenden kann, erhalten Sie die Zeilen im Allgemeinen in einer anderen Reihenfolge.

Vielleicht finden Sie diese Antwort, die ich zuvor geschrieben habe, informativ.

In PostgreSQL UPDATE s to rows können sie an eine andere Stelle innerhalb der Tabelle verschieben und die Reihenfolge ändern, in der sie zurückgegeben werden. Dasselbe gilt für den Hintergrund-Autovacuum-Prozess und verschiedene andere Operationen wie VACUUM und CLUSTER .

Sie dürfen also niemals Verlassen Sie sich für alles auf die "Standard" -Bestellung. Wenn Sie Zeilen eine gewisse Ordnung geben wollen, müssen sie müssen haben einen Schlüssel, nach dem Sie sie sortieren können.

Wenn Sie eine Tabelle ohne Schlüssel erstellt haben und jetzt feststellen, dass sie einen Schlüssel haben sollte, können Sie die Situation möglicherweise beheben, indem Sie ctid verwenden Systemspalte. nicht Verlassen Sie sich bei Produktionszwecken darauf, es handelt sich um eine systeminterne Spalte, die für Benutzer nur zu Wiederherstellungs- und Diagnosezwecken im Notfall sichtbar ist. Prüfen Sie zunächst, ob die physische Reihenfolge auf der Festplatte tatsächlich der gewünschten Reihenfolge entspricht:

SELECT row_number() OVER () AS mytable_id, *
FROM mytable
ORDER BY ctid;

Wenn dies der Fall ist, können Sie eine neue Schlüsselspalte hinzufügen, die auf einen automatisch inkrementierten Schlüssel voreingestellt ist, der in der Zeilenreihenfolge auf der Festplatte angewendet wird. Dazu gibt es zwei Möglichkeiten. Am sichersten ist:

BEGIN;
LOCK TABLE mytable IN ACCESS EXCLUSIVE MODE;
ALTER TABLE mytable RENAME TO mytable_old;

CREATE TABLE mytable (id SERIAL PRIMARY KEY, LIKE mytable_old INCLUDING ALL);

INSERT INTO mytable
SELECT row_number() OVER () AS id, *
FROM mytable_old
ORDER BY ctid;

SELECT setval('mytable_id_seq', (SELECT max(id)+1 FROM mytable));

COMMIT;

Wenn Sie dann sicher sind, dass Sie mit den Ergebnissen zufrieden sind, DROP TABLE mytable_old; . Sehen Sie sich diese Demo an:http://sqlfiddle.com/#!12/2cb99/2

Ein schneller und einfacher, aber weniger sicherer Weg besteht darin, einfach die Spalte zu erstellen und sich darauf zu verlassen, dass PostgreSQL die Tabelle von Anfang bis Ende neu schreibt:

ALTER TABLE mytable ADD COLUMN mytable_id SERIAL PRIMARY KEY;

Es gibt absolut keine Garantie dass PostgreSQL die IDs der Reihe nach zuweist, obwohl es dies in der Praxis tun wird. Sehen Sie sich diese SQLFiddle-Demo an.

Beachten Sie dies, wenn Sie eine SEQUENCE verwenden (was eine SERIAL Spalte erstellt) gibt es einige Verhaltensweisen, die Sie möglicherweise nicht erwarten. Wenn Sie mehrere Zeilen gleichzeitig einfügen, erhalten die Zeilen möglicherweise nicht unbedingt genau in der erwarteten Reihenfolge zugewiesene IDs, und sie werden möglicherweise in einer anderen Reihenfolge "erscheint" (sichtbar) als in der Reihenfolge, in der ihnen IDs zugewiesen und eingefügt wurden in. Auch wenn Transaktionen zurückgesetzt werden, wird die generierte ID für immer weggeworfen, sodass Sie Lücken in der Nummerierung erhalten. Dies ist sehr gut, wenn Sie möchten, dass Ihre Datenbank schnell ist, aber es ist nicht ideal, wenn Sie eine lückenlose Nummerierung wünschen. Suchen Sie in diesem Fall nach „postgresql gapless sequence“.