12.032014

Tabellen aufräumen in PostgreSQL

Welcher Softwareentwickler kennt es nicht? Eine Datenbanktabelle wird immer größer und größer. Abfragen auf diese Tabelle werden immer langsamer, die Indizes wachsen stetig und Wartungsarbeiten wie bspw. das Reindizieren werden nahezu unmöglich, da sie immer länger dauern und somit Zugriffe auf diese Tabelle immer länge blockieren.

Oft kann man auf bestimmte Einträge gut verzichten, da sie schon sehr alt sind oder als "gelöscht" markiert wurden. Wirklich löschen darf man sie aber auch nicht, im Notfall möchte man ja noch darauf zugreifen können.

Was tut man also? Man verschiebt die nicht mehr benötigten Zeilen in eine andere Tabelle, eine Archivtabelle.

Eine mögliche, aber sehr ineffiziente Lösung wäre es, sich in einem Script alle "löschbaren" Zeilen zu holen, in die Archivtabelle einzutragen und sie anschließend aus der originalen Tabelle zu löschen. Eine ziemlich unschöne Lösung, da man hiermit unnötig Netzwerktraffic auf dem Datenbankserver erzeugt.

Eine zweite Möglichkeit wäre in PostgreSQL eine Function zu erstellen, welche die Steps "Select", "Insert" und "Delete" nacheinander ausführt. Kann man machen, da ich aber kein großer Fan von Datenbankfunktionen bin und alles, was auch ohne sie geht, auch ohne sie erledigen möchte, scheidet auch diese Lösung für mich aus.

Stattdessen können wir in PostgresSQL das WITH Schlüsselwort verwenden, das sieht dann so aus:

WITH
t1 AS (DELETE FROM original_table RETURNING *),
t2 AS (INSERT INTO archive_table (SELECT * FROM t1) RETURNING *)
SELECT count(*) FROM t2;

Was passiert dort genau? Im ersten Teil der Query löschen wir alles aus "original_table", hier kann man natuerlich eine beliebige WHERE-Clause angeben! Besonders wichtig ist das "RETURNING *" am Ende, damit werden alle gelöschten Zeilen zurueckgegeben. Im zweiten Teil der Query werden dann genau diese Zeilen in die Tabelle "archive_table" eingetragen. Zu guter Letzt geben wir auch diese Eintraege wieder zurueck um uns dann am Ende anzeigen zu lassen, wieviele Rows wirklich in "archive_table" eingetragen wurden.

Ich bin mir sicher, das wird dem einen oder anderen das Leben etwas erleichtern, wenn es darum geht, Daten aus einer Postgre Datenbanktabelle zu archivieren.

Gruß