Werkzeuge 23.09.2010 - 09:43
Schlagwörter: Datenbanken
Angesichts zahlreicher neuer Funktionen haben sich die PostgreSQL-Entwickler zu einem großen Sprung entschlossen: Version 9 bringt erstmals eingebaute Replikation mit. Weitere Neuerungen wie die bedingte Trigger-Ausführung erleichtern Entwicklern die alltägliche Arbeit.
In das neue PostgreSQL-Release sind im Laufe des vergangenen Jahres fast 140 Patches eingeflossen – nicht nur Fehlerkorrekturen, sondern auch zahlreiche neue Funktionen. Die PostgreSQL Global Development Group hat sich aufgrund der umfangreichen Neuerungen insbesondere bei der Replikation für einen großen Sprung in der Versionsnummer auf 9.0 entschieden.
Viele Änderungen betreffen Entwickler. So stehen ihnen benannte Parameter in Stored Procedures zur Verfügung, und sie können Default-Werte im Funktionskopf vorgeben. Beides illustriert das folgende Listing mit einer vereinfachten Routine zum Ausschneiden von Teil-Strings.
CREATE OR REPLACE FUNCTION my_substr (
IN data TEXT,
IN d_start INTEGER DEFAULT 1,
IN d_length INTEGER DEFAULT 1,
OUT result TEXT)
AS $$ BEGIN
result := SUBSTR(data, d_start, d_length);
END; $$ LANGUAGE 'plpgsql' STRICT;
SELECT my_substr(4 AS d_length, 'PostgreSQL' AS data);
my_substr
----------------
Post
(1 Zeile)
Durch die explizite Benennung der Parameter ist es nun möglich, einzelne Argumente auszulassen beziehungsweise nur benötigte zu übergeben. Die Definition unzähliger Wrapper für alle möglichen Kombinationen von Übergabewerten entfällt. Diese Neuerung funktioniert mit allen serverseitigen Sprachen, die benannte Parameter unterstützen (unter anderem pl/pgSQL, pl/Perl und pl/Python).
DO führt Code-Blöcke aus, ohne dass man dafür eine Funktion erstellt. Das folgende Beispiel demonstriert dies, indem es alle Verbindungen zur Datenbank außer der eigenen beendet.
DO LANGUAGE plpgsql $$
DECLARE r RECORD;
BEGIN
FOR r IN SELECT procpid
FROM pg_stat_activity
WHERE procpid != pg_backend_pid()
LOOP
RAISE NOTICE 'Terminiere PID: %', r.procpid;
PERFORM pg_terminate_backend(r.procpid);
END LOOP;
END$$;
Das erlaubt dem Administrator zum Beispiel, vor einem System-Upgrade alle Benutzer abzumelden. Der DO-Aufruf darf keine Argumente enthalten und liefert kein Ergebnis zurück. Die Voreinstellung für seinen optionalen Parameter LANGUAGE ist pl/pgSQL, derselbe Wert gilt für Stored Procedures, wenn in ihrer Definition keine andere Wahl getroffen ist.
"Exclusion Constraints" haben nichts mit der bereits existierenden Konfigurationsoption constraint_exclusion zu tun. Vielmehr erlauben sie das Definieren von Einschränkungen, die über einen einzelnen Datensatz hinausgehen, wenn etwa nichtüberlappende geografische Daten oder Zeiträume gefordert sind.
Zur Illustration zeigt das folgende Code-Fragment die Buchungen eines Besprechungsraums. Es verwendet den Datentyp PERIOD, der Zeitspannen repräsentiert. Alternativ ließe sich ein selbst erstellter Datentyp mit Start- und Endzeit benutzen.
CREATE TABLE buchungen (
beschreibung TEXT,
raum TEXT,
zeit PERIOD,
EXCLUDE USING gist
(raum WITH =, zeit WITH &&) )
Die hinter EXCLUDE notierte Bedingung prüft, ob sich bei identischem Wert von raum die zeit-Intervalle überlappen. && ist der neue Überlappungs-Operator, der Spalten und Ausdrücke auswertet. gist steht für den verwendeten Indextyp, derzeit wird nur dieser eine unterstützt. In einer Exclusion Constraint sind mehrfache Prüfungen möglich, indem man für jede EXCLUDE-Klausel eine angibt.
Früher übertrug PostgreSQL beim Kopieren einer Tabelle mit CREATE TABLE … LIKE nur die Struktur der Tabelle. Diese Einschränkung ist verschwunden, es kopiert außerdem Kommentare und Storage-Optionen (etwa die Autovacuum-Einstellungen). EXPLAIN gibt den Query-Plan nun in verschiedenen Formaten aus und bietet Schalter zum Steuern von Detaileinstellungen. So liefert VERBOSE umfangreichere Ausgaben, beispielsweise in jedem Schritt die zurückgelieferten Spalten. COSTS informiert über die erwarteten Kosten. Die tatsächlich anfallenden ermittelt EXPLAIN, gibt man zusätzlich ANALYZE an.
BUFFERS liefert Informationen über gelesene oder geschriebene Buffer und ergibt nur im Zusammenhang mit ANALYZE Sinn. FORMAT schließlich wählt das Ausgabeformat, möglich sind TEXT, YAML, XML und JSON. Das folgende Beispiel zeigt die Ausgabe an einem simplen Beispiel.
EXPLAIN ( ANALYZE TRUE, COSTS TRUE,
BUFFERS TRUE, FORMAT TEXT )
SELECT * FROM pg_views ;
QUERY PLAN
------------------------------------------------------------
Hash Left Join (cost=1.14..12.87 rows=84 width=136)
(actual time=16.483..438.862 rows=84 loops=1)
Hash Cond: (c.relnamespace = n.oid)
Buffers: shared hit=2566 read=79
-> Seq Scan on pg_class c (cost=0.00..10.16 rows=84 width=76)
(actual time=0.046..0.438 rows=84 loops=1)
Filter: (relkind = 'v'::"char")
Buffers: shared hit=7
-> Hash (cost=1.06..1.06 rows=6 width=68)
(actual time=0.025..0.025 rows=6 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 1kB
Buffers: shared hit=1
-> Seq Scan on pg_namespace n
(cost=0.00..1.06 rows=6 width=68)
(actual time=0.003..0.012 rows=6 loops=1)
Buffers: shared hit=1
Total runtime: 439.026 ms
Ein Trigger darf neuerdings eine WHEN-Bedingung enthalten. Das ermöglicht das Prüfen von Bedingungen, ohne die Trigger-Funktion selbst auszulösen, etwa folgendermaßen:
CREATE TRIGGER test_trigger
BEFORE INSERT ON test
FOR EACH ROW
WHEN NEW.data != OLD.data
EXECUTE PROCEDURE trigger_function();
PostgreSQL ruft trigger_function in diesem Fall nur auf, wenn sich NEW.data und OLD.data unterscheiden. NEW und OLD stehen wie innerhalb der Trigger- Funktion zur Verfügung, Subselects sind in der WHEN-Bedingung jedoch nicht möglich.
Auf der nächsten Seite: Neuerungen 1