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

Teilen Sie Ihre Daten mit PostgreSQL 11

Version 10 von PostgreSQL hat die deklarative Tabellenpartitionierung hinzugefügt Feature.In Version 11 (derzeit in Beta) können Sie dies mit fremden Datawrappern kombinieren , das einen Mechanismus zum nativen Sharding Ihrer Tabellen über mehrere PostgreSQL-Server bereitstellt.

Deklarative Partitionierung

Betrachten Sie eine Tabelle, die die täglichen minimalen und maximalen Temperaturen von Städten für jeden Tag speichert:

CREATE TABLE temperatures (
    at      date,
    city    text,
    mintemp integer,
    maxtemp integer
);

Die Tabellenspezifikation ist absichtlich frei von Spaltenbeschränkungen und Primärschlüsseln, um die Dinge einfach zu halten – wir werden diese später hinzufügen.

Es kommt sehr häufig vor, dass in vielen Anwendungen häufiger auf die neuesten Daten zugegriffen wird. Denken Sie an das aktuelle Geschäftsjahr, diesen Monat, die letzte Stunde und so weiter. Wenn unsere Tabelle „Temperaturen“ wächst, ist es sinnvoll, die alten Daten in eine andere Tabelle mit derselben Struktur zu verschieben. Wir können zum Beispiel Folgendes tun:

CREATE TABLE temperatures_2017 (LIKE temperatures);
INSERT INTO temperatures_2017 SELECT * FROM temperatures WHERE
	extract(year from at) = 2017;
DELETE FROM temperatures WHERE extract(year from at) = 2017;

um alle Einträge aus dem Jahr 2017 in eine andere Tabelle zu verschieben. Dadurch bleibt die Haupttabelle „Temperaturen“ kleiner und schneller, damit die Anwendung damit arbeiten kann. Als Bonus können Sie, wenn Sie jetzt alte Daten löschen müssen, dies tun, ohne das Einfügen eingehender Daten in die Haupt-/aktuelle Tabelle zu verlangsamen, da die alten Daten leben in einer anderen Tabelle.

Aber mehrere unterschiedliche Tabellen zu haben, bedeutet, dass sich der Anwendungscode jetzt ändern muss. Wenn es auf ältere Daten zugreifen muss, um zum Beispiel die jährlichen Mindest- und Höchsttemperaturen einer Stadt zu erhalten, muss es jetzt herausfinden, welche Tabellen im Schema vorhanden sind, jede von ihnen abfragen und die Ergebnisse aus jeder Tabelle kombinieren. Können wir dies tun, ohne den Anwendungscode zu ändern?

Die Partitionierung macht dies möglich. In PostgreSQL 10 können Sie die Tabelle „Temperaturen“ wie folgt erstellen:

CREATE TABLE temperatures (
    at      date,
    city    text,
    mintemp integer,
    maxtemp integer
)
PARTITION BY RANGE (at);

Dies macht „temperatures“ zu einer Partitions-Master-Tabelle und teilt PostgreSQL mit, dass wir mehrere partitionierte Tabellen erstellen werden, die nicht überlappende Daten speichern, jede mit einem anderen Satz von „at“-Werten. Die Haupttabelle selbst enthält keine Daten, kann aber von der Anwendung abgefragt und eingefügt werden – die die untergeordneten Partitionen, die die eigentlichen Daten enthalten, nicht kennt.

Und hier sind unsere Partitionen:

CREATE TABLE temperatures_2017
    PARTITION OF temperatures
    FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');

CREATE TABLE temperatures_2018
    PARTITION OF temperatures
    FOR VALUES FROM ('2018-01-01') TO ('2019-01-01');

Wir haben jetzt zwei Tabellen, eine, die Daten für 2017 und eine andere für 2018 speichert. Beachten Sie, dass der „von“-Wert inklusive ist, der „bis“-Wert jedoch nicht. Probieren wir es aus:

temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-#        VALUES ('2018-08-03', 'London', 63, 90);
INSERT 0 1
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-#        VALUES ('2017-08-03', 'London', 59, 70);
INSERT 0 1
temp=# SELECT * FROM temperatures;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2017-08-03 | London |      59 |      70
 2018-08-03 | London |      63 |      90
(2 rows)

temp=# SELECT * FROM temperatures_2017;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2017-08-03 | London |      59 |      70
(1 row)

temp=# SELECT * FROM temperatures_2018;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2018-08-03 | London |      63 |      90
(1 row)

Die „Anwendung“ kann in die Haupttabelle einfügen und daraus auswählen, aber PostgreSQL leitet die eigentlichen Daten in die entsprechenden untergeordneten Tabellen weiter. (Oh und BTW, diese Temperaturen sind echt!)

Indizes und Einschränkungen

Indizes und Tabellen- und Spalteneinschränkungen werden tatsächlich auf Partitionstabellenebene definiert, da sich dort die eigentlichen Daten befinden. Sie können diese während der Erstellung der Partitionstabelle festlegen:

CREATE TABLE temperatures_2017
    PARTITION OF temperatures (
        mintemp NOT NULL,
        maxtemp NOT NULL,
        CHECK (mintemp <= maxtemp),
        PRIMARY KEY (at, city)
    )
    FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');

Mit PostgreSQL 11 können Sie Indizes für die übergeordnete Tabelle definieren und Indizes für vorhandene und zukünftige Partitionstabellen erstellen. Lesen Sie hier mehr.

Wrapper für fremde Daten

Die Foreign-Data-Wrapper-Funktionalität existiert seit einiger Zeit in Postgres. Mit PostgreSQL können Sie über diesen Mechanismus auf Daten zugreifen, die auf anderen Servern und Systemen gespeichert sind. Was uns interessiert, ist „postgres_fdw“, was es uns ermöglicht, von einem anderen auf einen Postgres-Server zuzugreifen.

„postgres_fdw“ ist eine in der Standarddistribution vorhandene Erweiterung, die mit dem regulären CREATE EXTENSION-Befehl installiert werden kann:

CREATE EXTENSION postgres_fdw;

Nehmen wir an, Sie haben einen weiteren PostgreSQL-Server „box2“ mit einer Datenbank namens „box2db“. Dazu können Sie einen „fremden Server“ erstellen:

CREATE SERVER box2 FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host 'box2', dbname 'box2db');

Lassen Sie uns auch unseren Benutzer „alice“ (der Benutzer, als der Sie angemeldet sind) dem box2-Benutzer „box2alice“ zuordnen. Dadurch kann „alice“ „box2alice“ sein, wenn auf entfernte Tabellen zugegriffen wird:

CREATE USER MAPPING FOR alice SERVER box2
    OPTIONS (user 'box2alice');

Sie können jetzt auf Tabellen (auch Ansichten, Matviews usw.) auf Box2 zugreifen. Erstellen Sie zuerst eine Tabelle auf Box2 und dann eine „Fremdtabelle“ auf Ihrem Server. Die Fremdtabelle enthält keine eigentlichen Daten, sondern dient als Proxy für den Zugriff auf die Tabelle auf box2.

-- on box2
CREATE TABLE foo (a int);

-- on your server
IMPORT FOREIGN SCHEMA public LIMIT TO (foo)
    FROM SERVER box2 INTO public;

Die Fremdtabelle auf Ihrem Server kann genauso an Transaktionen teilnehmen wie normale Tabellen. Anwendungen müssen nicht wissen, dass die Tabellen, mit denen sie interagiert, lokal oder fremd sind – wenn Ihre Anwendung jedoch ein SELECT ausführt, das viele Zeilen aus einer fremden Tabelle einziehen könnte, könnte dies die Dinge verlangsamen. In Postgres 10 wurden Verbesserungen für das Herunterdrücken von Joins vorgenommen und auf dem Remote-Server aggregieren.

Partitionierung und FDW kombinieren

Und jetzt zum lustigen Teil:Partitionen auf entfernten Servern einrichten.

Lassen Sie uns zuerst die physische Partitionstabelle auf box2 erstellen:

-- on box2
CREATE TABLE temperatures_2016 (
    at      date,
    city    text,
    mintemp integer,
    maxtemp integer
);

Und erstellen Sie dann die Partition auf Ihrem Server als Fremdtabelle:

CREATE FOREIGN TABLE temperatures_2016
    PARTITION OF temperatures
    FOR VALUES FROM ('2016-01-01') TO ('2017-01-01')
    SERVER box2;

Sie können jetzt Ihren eigenen Server einfügen und abfragen:

temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-#     VALUES ('2016-08-03', 'London', 63, 73);
INSERT 0 1
temp=# SELECT * FROM temperatures ORDER BY at;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2016-08-03 | London |      63 |      73
 2017-08-03 | London |      59 |      70
 2018-08-03 | London |      63 |      90
(3 rows)

temp=# SELECT * FROM temperatures_2016;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2016-08-03 | London |      63 |      73
(1 row)

Hier hast du es! Die Möglichkeit, Zeilen in eine Remote-Partition einzufügen, ist neu in Version 11. Mit dieser Funktion können Sie Ihre Daten jetzt logisch (Partitionen) und physisch (FDW) teilen.

Datenverwaltung

Befehle wie VACUUM und ANALYZE funktionieren erwartungsgemäß mit Partitionsmastertabellen – alle lokalen untergeordneten Tabellen unterliegen VACUUM und ANALYZE. Partitionen können getrennt werden, ihre Daten können ohne die Partitionseinschränkung bearbeitet und dann wieder angefügt werden. Untergeordnete Partitionstabellen selbst können partitioniert werden.

Das Verschieben von Daten („Resharding“) kann mit regulären SQL-Anweisungen (Einfügen, Löschen, Kopieren usw.) erfolgen. Partitionslokale Indizes und Trigger können erstellt werden.

Das Hinzufügen von Redundanz zu Ihren Shards lässt sich leicht mit logischer oder Streaming-Replikation erreichen.