Nach dem Treffen "PostgreSQL 11 New Features"

Heute werden wir über die wichtigsten Funktionen von PostgreSQL 11 sprechen. Warum nur über sie - weil nicht jeder einige Funktionen benötigt, haben wir uns für die beliebtesten entschieden.

Inhalt




Jit-Zusammenstellung


PostgreSQL hat endlich die JIT-Kompilierung eingeführt, dh das Kompilieren von Abfragen in Binärcode. Kompilieren Sie dazu PostgreSQL mit Unterstützung für die JIT-Kompilierung (Compile time 1 (--with-llvm)) . Gleichzeitig muss die Maschine eine LLVM-Version von mindestens 3.9 haben.

Was kann JIT beschleunigen?

  • Abfragen mit der WHERE-Klausel, dh alles, was nach diesem Schlüsselwort steht. Dies ist nicht immer notwendig, aber die Gelegenheit ist nützlich.
  • Berechnung der Zielliste: In der PostgreSQL-Terminologie ist dies alles, was zwischen select und from liegt.
  • Aggregate.
  • Konvertieren Sie Datensätze von einer Ansicht in eine andere (Projektion). Wenn Sie beispielsweise Join auf zwei Tabellen anwenden, ist das Ergebnis ein neues Tupel, das Felder aus beiden Tabellen enthält.
  • Tupel verformt sich. Eines der Probleme einer Datenbank, zumindest in relationalen Kleinbuchstaben, besteht darin, ein Feld aus einem Datensatz auf der Festplatte abzurufen. Schließlich kann es null geben, sie haben unterschiedliche Datensätze und im Allgemeinen ist dies nicht die billigste Operation.

Compile time 2 bedeutet, dass JIT nicht verwendet wird. In PostgreSQL gibt es einen Moment der Abfrageplanung, in dem das System entscheidet, was JIT wert ist und was nicht. Zu diesem Zeitpunkt wird es JITs und dann wird der Executor so ausgeführt, wie er ist.

JIT ist steckbar. Standardmäßig funktioniert es mit LLVM, Sie können jedoch jede andere JIT verbinden.



Wenn Sie PostgreSQL ohne JIT-Unterstützung kompiliert haben, funktioniert das allererste Setup nicht. Implementierte Optionen für Entwickler, es gibt Einstellungen für einzelne JIT-Funktionen.

Der nächste subtile Punkt bezieht sich auf jit_above_cost. JIT selbst ist nicht kostenlos. Daher verwendet PostgreSQL standardmäßig die JIT-Optimierung, wenn die Kosten einer Abfrage 100.000 bedingte Papageien überschreiten, in denen Erklärungen, Analysen usw. gemessen werden. Dieser Wert wird zufällig ausgewählt, achten Sie also darauf.

Aber nicht immer nach dem Einschalten von JIT funktioniert alles sofort. Normalerweise experimentiert jeder mit JIT mithilfe der Tabelle select * from, bei der die Abfrage id = 600 ist, und sie schlagen fehl. Wahrscheinlich ist es notwendig, die Anfrage irgendwie zu komplizieren, und dann generiert jeder eine riesige Datenbank und erstellt die Anfrage. Infolgedessen beruht PostgreSQL auf den Funktionen der Festplatte, da die Kapazität für gemeinsam genutzte Puffer und Caches fehlt.

Hier ist ein völlig abstraktes Beispiel. Es gibt 9 Nullfelder mit unterschiedlichen Frequenzen, sodass Sie den Effekt der Tupelverformung feststellen können.

select i as x1,
case when i % 2 = 0 then i else null end as x2,
case when i % 3 = 0 then i else null end as x3,
case when i % 4 = 0 then i else null end as x4,
case when i % 5 = 0 then i else null end as x5,
case when i % 6 = 0 then i else null end as x6,
case when i % 7 = 0 then i else null end as x7,
case when i % 8 = 0 then i else null end as x8,
case when i % 9 = 0 then i else null end as x9
into t
from generate_series(0, 10000000) i;

vacuum t;
analyze t;


PostgreSQL bietet viele Möglichkeiten. Um die Vorteile von JIT zu erkennen, deaktivieren Sie die ersten beiden Zeilen, um nicht zu stören, und setzen Sie die Schwellenwerte zurück.

set max_parallel_workers=0;
set max_parallel_workers_per_gather=0;
set jit_above_cost=0;
set jit_inline_above_cost=0;
set jit_optimize_above_cost=0;


Hier ist die Anfrage selbst:

set jit=off;
explain analyze
select count(*) from t where
sqrt(pow(x9, 2) + pow(x8,2)) < 10000;

set jit=on;
explain analyze
select count(*) from t where
sqrt(pow(x9, 2) + pow(x8,2)) < 10000;


Und hier ist das Ergebnis:

Planning Time: 0.71 ms
Execution Time: 1986.323 ms

VS

Planning Time: 0.060 ms
JIT:
Functions: 4
Generation Time: 0.911 ms
Inlining: true
Inlining Time: 23.876 ms
Optimization: true
Optimization Time: 41.399 ms
Emission Time: 21.856 ms
Execution Time: 949.112 ms


JIT hat dazu beigetragen, die Anfrage um die Hälfte zu beschleunigen. Die Planungszeit ist ungefähr gleich, aber dies ist höchstwahrscheinlich das Ergebnis des Zwischenspeicherns von PostgreSQL. Ignorieren Sie es also.

Zusammenfassend dauerte die JIT-Kompilierung etwa 80 ms. Warum ist JIT nicht kostenlos? Bevor Sie die Anforderung ausführen, müssen Sie sie kompilieren. Dies nimmt auch Zeit in Anspruch. Und drei Größenordnungen mehr als geplant. Kein teures Vergnügen, aber es zahlt sich aufgrund der Länge der Ausführung aus.

Auf diese Weise können Sie JIT verwenden, obwohl dies nicht immer von Vorteil ist.

Partitionierung


Wenn Sie auf die Partitionierung in PostgreSQL geachtet haben, haben Sie wahrscheinlich bemerkt, dass sie dort für die Show erstellt wurde. In Version 10 verbesserte sich die Situation geringfügig, als eine deklarative Deklaration von Partitionen (Abschnitten) erschien. Auf der anderen Seite blieb alles innen gleich und funktionierte ungefähr gleich wie in früheren Versionen, das heißt schlecht.
In vielerlei Hinsicht wurde dieses Problem durch das Modul pg_pathman gelöst, das es ermöglichte, mit Abschnitten zu arbeiten und sie zur Laufzeit optimal genug abzuschneiden.

In Version 11 wurde die Partitionierung erheblich verbessert:

  • Erstens kann die Partitionstabelle einen Primärschlüssel haben, der den Partitionsschlüssel enthalten muss. Tatsächlich ist dies entweder ein Halbprimärschlüssel oder ein Primärhalbschlüssel. Leider können Sie keinen Fremdschlüssel darauf erstellen. Ich hoffe, dass dies in Zukunft behoben wird.
  • Auch jetzt ist es möglich, nicht nur nach Bereich, sondern auch nach Liste und Hash zu partitionieren. Der Hash ist ziemlich primitiv, der Rest des Ausdrucks wird dafür genommen.
  • Beim Aktualisieren wird die Linie zwischen Abschnitten verschoben. Früher mussten Sie einen Trigger schreiben, jetzt erfolgt dies automatisch.

Die große Frage ist: Wie viele Abschnitte kann ich haben? Ehrlich gesagt, mit einer großen Anzahl von Abschnitten (Tausende und Zehntausende) funktioniert die Funktion nicht gut. Pg_pathman macht es besser.

Standardmäßig werden auch Abschnitte erstellt. Auch in pg_pathman können Sie Abschnitte automatisch erstellen, was bequemer ist. Hier fällt alles, was nicht irgendwohin geschoben werden konnte, in den Abschnitt. Wenn dies in einem realen System standardmäßig der Fall ist, dann bekommen Sie nach einiger Zeit ein solches Durcheinander, das Sie dann quälen, um zu harken.

PostgreSQL 11 kann jetzt die Partitionierung optimieren, wenn zwei Tabellen durch einen Partitionsschlüssel verbunden sind und die Partitionierungsschemata übereinstimmen. Dies wird durch einen speziellen Parameter gesteuert, der standardmäßig deaktiviert ist.

Sie können Aggregate für jeden Abschnitt separat berechnen und dann addieren. Schließlich können Sie einen Index für die übergeordnete partitionierte Tabelle erstellen. Anschließend werden lokale Indizes für alle damit verbundenen Tabellen erstellt.

Im Abschnitt „Was ist neu?“ Wird eine wunderbare Sache erwähnt - die Möglichkeit, Abschnitte bei der Ausführung einer Anforderung wegzuwerfen. Lassen Sie uns überprüfen, wie es funktioniert. Das Ergebnis ist eine solche Tabelle:



Wir machen einen Typ und eine Tabelle aus zwei Spalten mit einem Primärschlüssel, mit einer Bigserial-Spalte, fügen Sie die Daten ein. Wir erstellen die zweite Tabelle, die partitioniert wird und eine Kopie der ersten ist. Fügen Sie der partitionierten Tabelle den Primärschlüssel hinzu.



Die Tabelle besteht aus zwei Arten von Einträgen: "weibliche Kindermädchen" und "männliche Fahrer". Und es wird eine Fahrerin geben. Wir machen zwei Abschnitte, teilen durch Liste, fügen den Primärschlüssel hinzu und fügen alle Daten aus der Tabelle ein, in der all dies generiert wird. Das Ergebnis war völlig uninteressant:



Achten Sie auf die Anfrage. Wir wählen alles aus einer nicht partitionierten Tabelle aus und stellen eine Verbindung zu einer partitionierten Tabelle her. Wir nehmen ein kleines Stück und wählen nur einen Typ, sie gehen durch einen. Wir geben an, dass die Oss-Spalte einen Wert haben sollte. Es stellt sich eine Auswahl solider Treiber heraus.

Bei der Ausführung deaktivieren wir speziell die Parallelisierung, da PostgreSQL 11 standardmäßig sehr aktiv mehr oder weniger komplexe Abfragen parallelisiert. Wenn wir uns den Ausführungsplan ansehen (Analyse erklären), dann ist ersichtlich, dass das System die Daten in beiden Abschnitten hinzugefügt hat: im Kindermädchen und in den Fahrern, obwohl die Kindermädchen nicht da waren. Es gab keine Aufrufe an den Puffer. Zeitaufwand, verwendete Bedingung, obwohl PostgreSQL alles herausfinden konnte. Das heißt, die Partitionseliminierungsdeklaration funktioniert nicht sofort. Vielleicht wird dies in den nächsten Builds korrigiert. In diesem Fall funktioniert das Modul pg_pathman in diesem Fall problemlos.

Indizes


  • Gebotsoptimierung auf monotone Weise, d. H. B-Baum. Jeder weiß, dass das Einfügen von monoton wachsenden Daten nicht sehr schnell erfolgt. Jetzt kann PostgreSQL die Endseite auf besondere Weise zwischenspeichern und nicht mehr vom Stamm bis zum Einfügen. Dies beschleunigt die Arbeit erheblich.
  • PostgreSQL 10 ermöglichte die Verwendung eines Hash-Index, da WAL (Write Ahead-Protokoll) verwendet wurde. Zuvor haben wir den Wert erhalten, die Seite entsperrt und den Wert zurückgegeben. Für den nächsten Wert mussten Sie die Seite erneut blockieren, zurückkehren, entsperren und so weiter. Jetzt ist der Hash viel schneller geworden. Sie können jeweils eine Seite blockieren, um einen Datensatz aus einem Hash-Index abzurufen, alle Werte von dort zurückzugeben und ihn zu entsperren. Jetzt ist es für HASH, GiST und GIN implementiert. Dies wird voraussichtlich in Zukunft für SP-GiST implementiert. Für BRIN mit seiner Min / Max-Logik ist dies jedoch grundsätzlich nicht möglich.
  • Wenn Sie früher Funktionsindizes erstellt haben, wurde das HOT-Update (Heap Only Tuple) effektiv deaktiviert. Wenn ein Datensatz in PostgreSQL aktualisiert wird, wird tatsächlich eine neue Kopie erstellt. Dazu muss in alle Indizes in der Tabelle eingefügt werden, damit der neue Wert auf das neue Tupel verweist. Eine solche Optimierung ist seit langem implementiert: Wenn das Update keine Felder ändert, die nicht in den Indizes enthalten sind, und auf derselben Seite freier Speicherplatz vorhanden ist, werden die Indizes nicht aktualisiert, und in der alten Version von Tupel wird ein Zeiger auf die neue Version gesetzt. Auf diese Weise können Sie die Schwere des Problems mit Updates etwas verringern. Eine solche Optimierung funktionierte jedoch überhaupt nicht, wenn Sie Funktionsindizes hatten. In PostgreSQL 11 begann es zu funktionieren. Wenn Sie einen Funktionsindex erstellt und ein Tupel aktualisiert haben, das nicht ändert, wovon der Funktionsindex abhängt, funktioniert das HOT-Update.

Deckungsindizes


Diese Funktionalität wurde vor drei Jahren von PostgresPro implementiert, und PostgreSQL hat die ganze Zeit versucht, sie hinzuzufügen. Durch das Abdecken von Indizes können Sie dem eindeutigen Index direkt im Indextupel zusätzliche Spalten hinzufügen.

Warum? Jeder liebt den Nur-Index-Scan für seine schnelle Arbeit. Hierzu werden bedingt „abdeckende“ Indizes erstellt:



Gleichzeitig müssen Sie die Einzigartigkeit bewahren. Daher werden zwei Indizes erstellt, schmal und breit.
Der Nachteil ist, dass Sie beim Anwenden von Vakuum, Einfügen oder Aktualisieren einer Tabelle beide Indizes aktualisieren müssen. Das Einfügen in einen Index ist also eine langsame Operation. Mit dem Deckungsindex kann nur ein Index verwaltet werden.

Es stimmt, er hat einige Einschränkungen. Genauer gesagt, die Vorteile, die möglicherweise nicht sofort verstanden werden. Die Spalten c und d im ersten Erstellungsindex müssen keine Skalartypen sein, für die ein B-Tree-Index definiert ist. Das heißt, sie haben nicht unbedingt einen mehr-weniger-Vergleich. Es können Punkte oder Polygone sein. Das einzige ist, dass das Tupel weniger als 2,7 KB groß sein sollte, da der Index kein Toasten enthält, aber Sie können in das passen, was nicht verglichen werden kann.

Innerhalb des Index mit diesen garantierten Spalten werden bei der Suche jedoch keine Berechnungen durchgeführt. Dies sollte durch einen Filter erfolgen, der über dem Index steht. Berechnen Sie es einerseits innerhalb des Index, andererseits ist dies ein zusätzlicher Funktionsaufruf. Aber alles ist nicht so beängstigend, wie es scheint.

Außerdem können Sie diese abgedeckten Spalten zum Primärschlüssel hinzufügen.

SP GiST


Nur wenige Leute verwenden diesen Index, weil er ziemlich spezifisch ist. Trotzdem wurde es möglich, nicht ganz das darin zu speichern, was eingefügt wurde. Dies bezieht sich auf Verlustindex, Komprimierung. Nehmen Sie als Beispiel Polygone. Stattdessen wird ein Begrenzungsrahmen in den Index eingefügt, dh das minimale Rechteck, das das gewünschte Polygon enthält. In diesem Fall stellen wir das Rechteck als Punkt im vierdimensionalen Raum dar und arbeiten dann mit dem klassischen Quad3 im vierdimensionalen Raum.

Auch für den SP-GiST wurde die Operation "Präfixsuche" eingeführt. Es gibt true zurück, wenn eine Zeile ein Präfix einer anderen ist. Sie haben es nicht nur so eingeführt, sondern für eine solche Anfrage mit Unterstützung für SP-GiST.

SELECT * FROM table WHERE c ^@ „abc“

Im B-Tree gibt es eine Grenze von 2,7 Kb pro Zeile, SP-GiST jedoch nicht. Richtig, PostgreSQL hat eine Einschränkung: Ein einzelner Wert darf 1 GB nicht überschreiten.

Leistung


  • Es wurde nur ein Bitmap-Index-Scan angezeigt . Es funktioniert genauso wie der klassische Index-Scan, kann jedoch keine Reihenfolge garantieren. Daher gilt es nur für einige Aggregate wie count (*), da Bitmap keine Felder vom Index zum Executor übertragen kann. Er kann nur die Tatsache einer Aufzeichnung melden, die die Bedingungen erfüllt.
  • Die nächste Neuerung ist die Aktualisierung der Freiraumkarte während der Anwendung von Vakuum . Leider glaubt keiner der Entwickler von Systemen, die mit PostgreSQL arbeiten, dass es notwendig ist, am Ende der Tabelle zu löschen, da sonst Löcher und nicht zugewiesener Speicherplatz angezeigt werden. Um dies zu verfolgen, haben wir FSM implementiert, mit dem wir die Tabelle nicht vergrößern, sondern Tupel in Hohlräume einfügen können. Früher wurde dies mit Vakuum gemacht, aber am Ende. Und jetzt kann Vakuum dies in diesem Prozess tun, und in stark belasteten Systemen hilft es, die Tischgröße unter Kontrolle zu halten.
  • Möglichkeit, den Index-Scan während der Vakuumausführung zu überspringen . Tatsache ist, dass alle PostgreSQL-Indizes gemäß der Datenbanktheorie als sekundär bezeichnet werden. Dies bedeutet, dass Indizes außerhalb der Tabelle gespeichert werden und Zeiger von dort zu ihr führen. Mit dem Nur-Index-Scan können Sie diesen Sprung nicht auf Zeiger ausführen, sondern direkt aus dem Index entnehmen. Vakuum, das Datensätze löscht, kann sie jedoch nicht im Index anzeigen und entscheiden, ob sie gelöscht werden sollen oder nicht, einfach weil der Index keine solchen Daten enthält. Daher wird das Vakuum immer in zwei Durchgängen durchgeführt. Zuerst geht er die Tabelle durch und findet heraus, was er löschen muss. Dann geht es zu den an diese Tabelle angehängten Indizes, löscht die Datensätze, die sich auf die gefundenen beziehen, kehrt zur Tabelle zurück und löscht, was sie wollte. Und die Phase des Wechsels zu den Indizes ist nicht immer erforderlich.

    Wenn seit dem letzten Vakuum kein Löschen oder Aktualisieren stattgefunden hat, haben Sie keine toten Datensätze, Sie müssen sie nicht löschen. In diesem Fall können Sie nicht zum Index wechseln. Es gibt zusätzliche Feinheiten, b-tree löscht seine Seiten nicht sofort, sondern in zwei Durchgängen. Wenn Sie daher viele Daten in der Tabelle gelöscht haben, müssen Sie Vakuum erzeugen. Wenn Sie jedoch Speicherplatz in den Indizes freigeben möchten, saugen Sie zweimal.

    Jemand wird überrascht sein, in welcher Tabelle gab es kein Löschen oder Aktualisieren? In der Tat beschäftigen sich viele damit, denken einfach nicht. Hierbei handelt es sich nur um Anhänge-Tabellen, in denen beispielsweise Protokolle hinzugefügt werden. In ihnen ist die Entfernung äußerst selten. Dies spart erheblich die Dauer des Vakuums / Autovakuums, reduziert die Belastung der Festplatte, die Verwendung von Caches usw.
  • Gleichzeitiges Festschreiben wettbewerbsfähiger Transaktionen . Dies ist keine Innovation, sondern eine Verbesserung. Jetzt erkennt PostgreSQL, dass es jetzt festgeschrieben wird, und verzögert das Festschreiben der aktuellen Transaktion und wartet auf den Rest der Festschreibungen. Bitte beachten Sie, dass diese Funktion nur geringe Auswirkungen hat, wenn Sie einen kleinen Server mit 2 bis 4 Kernen haben.
  • postgres_fdw (Foreign Data Wrappers) . FDW ist eine Möglichkeit, eine externe Datenquelle so zu verbinden, dass sie wie ein echter Postkongress aussieht. Mit postgres_fdw können Sie eine Tabelle von einer benachbarten Instanz mit Ihrer Instanz verbinden, und sie sieht fast wie eine echte aus. Jetzt wurde eine der Einschränkungen für das Aktualisieren und Löschen entfernt. PostgreSQL kann oft erraten, dass Sie Rohdaten senden müssen. Die Ausführung der Join-Anforderung ist recht einfach: Wir führen sie auf unserem Computer aus, ziehen die Tabelle mit FDW aus der Instanz heraus, ermitteln den ID-Primärschlüssel, den wir löschen müssen, und wenden dann die Aktualisierung und / oder Löschung an, dh die Daten, die wir hin und her gehen . Jetzt ist es möglich zu tun. Wenn sich die Tabellen auf verschiedenen Computern befinden, ist dies natürlich nicht so einfach, aber mit FDW können Sie die Remote-Maschine dazu bringen, Vorgänge auszuführen, und wir haben nur gewartet.
  • toast_tuple_target . Es gibt Situationen, in denen die Daten geringfügig über die Grenzen hinausgehen, nach denen ein Toasten erforderlich ist, das gleichzeitige Toasten solcher Werte jedoch nicht immer angenehm ist. Angenommen, Sie haben ein Limit von 90 Bytes und müssen 100 anpassen. Sie müssen den Toast für 10 Bytes starten, sie separat hinzufügen. Wenn Sie dieses Feld auswählen, müssen Sie zum Toastindex gehen, herausfinden, wo sich die erforderlichen Daten befinden, und zur Toasttabelle gehen. sammeln und geben.

Mit Hilfe der Feinabstimmung können Sie dieses Verhalten jetzt für die gesamte Datenbank oder eine separate Tabelle ändern, sodass für solche kleinen Exits kein Toast erforderlich ist. Aber Sie müssen verstehen, was Sie tun, ohne das wird nichts funktionieren.

WAL


  • WAL (Write Ahead Log) ist ein Write Ahead Log. Die Größe des WAL-Segments wird jetzt in initdb festgelegt. Gott sei Dank, nicht beim Kompilieren.
  • Die Logik hat sich ebenfalls geändert. Zuvor wurde der Satz von WAL-Segmenten ab dem Zeitpunkt des vorletzten Kontrollpunkts und jetzt ab dem letzten gespeichert. Dies kann die gespeicherte Datenmenge erheblich reduzieren. Wenn Sie jedoch eine 1-TB-Datenbank haben und TPS = 1, dh eine Anforderung pro Sekunde, werden Sie den Unterschied nicht sehen.

Sicherung und Replikation


  • Abschneiden wurde in der logischen Replikation angezeigt . Es war die letzte DML-Operation, die sich nicht in der logischen Replikation widerspiegelte. Jetzt reflektiert.
  • In der logischen Replikation wurde eine Meldung zur Vorbereitung angezeigt . Jetzt können Sie die Vorbereitungstransaktion abfangen, eine zweiphasige Festschreibung bei der logischen Replikation. Dies wird für die Konstruktion von Clustern implementiert - heterogen, homogen, sharded und nicht schattiert, Multimaster und so weiter.
  • Ausnahme von pg_basebackup temporären und nicht protokollierten Tabellen . Viele haben sich beschwert, dass pg_basebackup die aufgelisteten Tabellen enthält. Und ohne sie reduzieren wir die Größe des Backups. Vorausgesetzt, Sie verwenden temporäre und nicht protokollierte Tabellen, ist diese Option für Sie ansonsten nutzlos.
  • Prüfsummensteuerung bei der Streaming-Replikation (für Tabellen) . Auf diese Weise können Sie nachvollziehen, was mit Ihrem Replikat passiert ist. Bisher ist die Funktion nur für Tabellen implementiert.
  • Es gab eine Förderung der Positionen der Replikationssteckplätze . Wie immer können Sie nur vorwärts und rückwärts wickeln, wenn es eine WAL gibt. Außerdem müssen Sie sehr gut verstehen, was Sie damit machen und warum. Meiner Meinung nach ist dies eher eine Entwicklungsoption, aber diejenigen, die für einige exotische Anwendungen die logische Replikation verwenden, können sie genießen.

Für dba


  • Tabelle ändern, Spalte hinzufügen, nicht Null Standard X , die gesamte Tabelle schreiben. Hierfür wird eine geringe Gebühr erhoben: Der Standardwert wird separat gespeichert. Wenn Sie Tupel aufnehmen und diese Spalte benötigen, muss PostgreSQL einem zusätzlichen Codierungspfad folgen, um einen temporären Wert abzurufen, ihn durch Tupel zu ersetzen und ihn Ihnen zu geben. Trotzdem kann man damit leben.
  • Vakuum / analysieren . Bisher konnten Sie nur Vakuum anwenden oder eine gesamte Datenbank oder eine einzelne Tabelle analysieren. Jetzt ist es möglich, dies mit einem Befehl für mehrere Tabellen durchzuführen.

Parallele Ausführung


  • Parallele Konstruktion von B-Tree-Indizes . In Version 11 wurde es möglich, B-Tree-Indizes in mehrere Worker einzubetten. Wenn Sie eine wirklich gute Maschine, viele Festplatten und viele Kerne haben, können Sie parallel Indizes erstellen. Dies verspricht eine spürbare Leistungssteigerung.
  • Parallele Hash-Verbindung unter Verwendung einer gemeinsam genutzten Hash-Tabelle für Ausführende . , -. , . - , . .
  • , union, create table as, select create materialized view!
  • - (limit) . .

:

alter table usr reset (parallel_workers)
create index on usr(lower((so).occ)) — 2
alter table usr set (parallel_workers=2)
create index on usr(upper((so).occ)) — 1.8


parallel worker. . 16 4 ( ) 2 ., — 1,8 . , , . , .

:

explain analyze
select u1.* from usr u, usr1 u1 where
u.id=u1.id+0


, . , user — , . . , , .

, PostgreSQL 11 .



1425 , 1,5 . 1,4 . 2 . , 9.6 : 1 — 1 ., 2 1 . , 10 tuple. 11 . : user, batch, x-scan append .

:



. 211 , 702 . , 510 1473. , 2 .

parallel hash join. . — 4. , .

parallel index scan . batch . Was bedeutet das? hash join, . user . , parallel hash, .

1 . , OLAP-, OLTP . OLTP , .


.

  • . , . , «» «», index scan, . (highly skewed data), , . . , , .
  • «», .

Window-


SQL:2011, .


, , . , , , , , .

websearch, . , . , .

# select websearch_to_tsquery('dog or cat');
----------------------
'dor' | 'cat'
# select websearch_to_tsquery('dog -cat');
----------------------
'dor' & !'cat'
# select websearch_to_tsquery('or cat');
----------------------
'cat'


— dog or cat — . Websearch . | , . “or cat”. , . websearch “or” . , -, .

Websearch — . : , . , .

Json(b)


10- , 11- . json json(b), tsvector. ( json(b)) - . , , , bull, numeric, string, . .

# select jsonb_to_tsvector
('{"a":"texts", "b":12}', '"string"');
-------------------
'text':1
# select jsonb_to_tsvector
('{"a":"texts", "b":12}', '["string", "numeric"]');
-------------------
'12':3 'text':1


json(b), . , , , .

PL/*


.

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
FOR i IN 0..9 LOOP
INSERT INTO test1 (a) VALUES (i);
IF i % 2 = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END LOOP;
END
$$;
CALL transaction_test1();


call, , . . . select, insert .

, , PostgreSQL . Perl, Python, TL PL/pgSQL. Perl sp begin, .

PL/pgSQL : , .

pgbench


pgbench ICSB bench — , , . if, , . case, - . --init-steps , , .

random-seed. zipfian- . / — , . - , , - , .

, , - .

PSQL


, PSQL, . exit quit.

  • — copy, 2 32 . copy : 2 32 - . , 2 31 2 32 copy . 64- , 2 64 .
  • POSIX : NaN 0 = 1 1 NaN = 1.

Source: https://habr.com/ru/post/de414031/


All Articles