Ich versuche, einige alte MySQL-Abfragen auf PostgreSQL zu portieren, aber ich habe Probleme mit dieser:
DELETE FROM logtable ORDER BY timestamp LIMIT 10;
PostgreSQL erlaubt keine Reihenfolge oder Einschränkungen in seiner Löschsyntax, und die Tabelle hat keinen Primärschlüssel, sodass ich keine Unterabfrage verwenden kann. Außerdem möchte ich das Verhalten beibehalten, bei dem die Abfrage genau die angegebene Anzahl oder Datensätze löscht. Wenn die Tabelle beispielsweise 30 Zeilen enthält, aber alle denselben Zeitstempel haben, möchte ich trotzdem 10 löschen, obwohl dies keine Rolle spielt welche 10.
So; Wie lösche ich eine feste Anzahl von Zeilen mit Sortierung in PostgreSQL?
Bearbeiten: Kein Primärschlüssel bedeutet, dass keine log_id
Spalte oder ähnliches vorhanden ist. Ah, die Freuden älterer Systeme!
quelle
alter table foo add column id serial primary key
.Antworten:
Sie könnten versuchen, Folgendes zu verwenden
ctid
:Das
ctid
ist:Es gibt
oid
aber auch nur das, wenn Sie beim Erstellen der Tabelle ausdrücklich danach fragen.quelle
VACUUM FULL
Autovakuum Probleme verursacht, wenn sie diectid
Werte in der Tabelle ändern, während die Abfrage ausgeführt wird?ctid
Dokumentation ist, dass siectid
stabil genug ist, damit dieses LÖSCHEN funktioniert, aber nicht stabil genug, um beispielsweise als Ghetto-FK in eine andere Tabelle aufgenommen zu werden. Vermutlich aktualisieren Sie das nicht,logtable
sodass Sie sich keine Gedanken über diese Änderungen machen müssen,ctid
undVACUUM FULL
sperren die Tabelle ( postgresql.org/docs/current/static/routine-vacuuming.html ), sodass Sie sich keine Sorgen machen müssen der andere Weg, denctid
s ändern kann. @ araqnids PostgreSQL-Fu ist ziemlich stark und die Dokumente stimmen ihm zu, um zu booten.Postgres-Dokumente empfehlen, Array anstelle von IN und Unterabfrage zu verwenden. Dies sollte viel schneller funktionieren
Diesen und einige andere Tricks finden Sie hier
quelle
any (array( ... ));
es schneller ist als dasin ( ... )
, klingt es wie ein Fehler im Abfrageoptimierer - es sollte in der Lage sein, diese Transformation zu erkennen und dasselbe mit den Daten selbst zu tun.IN
auf einerUPDATE
(was der Unterschied sein könnte).quelle
Angenommen, Sie möchten 10 Datensätze (ohne Bestellung) löschen, können Sie dies tun:
Für meinen Anwendungsfall, 10 Millionen Datensätze zu löschen, stellte sich heraus, dass dies schneller war.
quelle
Sie können eine Prozedur schreiben, die das Löschen für einzelne Zeilen durchläuft. Die Prozedur kann einen Parameter verwenden, um die Anzahl der Elemente anzugeben, die Sie löschen möchten. Aber das ist ein bisschen übertrieben im Vergleich zu MySQL.
quelle
Wenn Sie keinen Primärschlüssel haben, können Sie die Syntax Array Where IN mit einem zusammengesetzten Schlüssel verwenden.
Das hat bei mir funktioniert.
quelle