Wie viel ist neu im Dutzend des Teufels?

Wir sprechen nur über PostgreSQL 13. Am 8. April fand ein "Einfrieren" statt - das Einfrieren von PostgreSQL- Funktionen . Jetzt werden nur die Funktionen in diese Version aufgenommen, die vor diesem Datum akzeptiert wurden.

Es ist schwer, eine revolutionäre Version davon zu nennen. Es gibt keine wesentlichen konzeptionellen Änderungen. Darüber hinaus hatten so wichtige Patches wie Tabelle und Funktionen für den JSON / SQL-Standard, die ich in PG12 neben dem JSONPath-Patch sehen wollte, keine Zeit, ihn einzugeben. Ein vorgefertigter eingebetteter Speicher wurde nicht angezeigt - nur die Schnittstelle wird finalisiert. Die Liste der Verbesserungen ist jedoch immer noch beeindruckend. Wir haben eine ziemlich vollständige Zusammenfassung der Patches vorbereitet, die im Devil's Dozen enthalten sind.




Änderungen an SQL-Befehlen


CREATE DATABASE ... LOCALE

Dienstprogrammeinitdb,createdbund das TeamCREATE COLLATIONhaben eine EinstellungLOCALEdie Sie Werte für das Recht angeben kannLC_CTYPEundLC_COLLATE. Jetzt erschien die gleiche Gelegenheit im TeamCREATE DATABASE:

CREATE DATABASE db_koi8r TEMPLATE template0 
    ENCODING 'KOI8R' LOCALE 'ru_RU.KOI8R';

ALTER VIEW ... RENAME COLUMN

Der Spaltenname in der Ansicht kann jetzt mit dem Befehl geändert werdenALTER VIEW. Zuvor musste die Ansicht neu erstellt werden.

Angenommen, Sie haben vergessen, der Spalte einen Namen zu geben:

CREATE VIEW uptime AS SELECT current_timestamp, current_timestamp - pg_postmaster_start_time();
SELECT * FROM uptime;

       current_timestamp       |    ?column?     
-------------------------------+-----------------
 2020-03-23 15:37:00.088824+03 | 04:18:24.897856

Es kann behoben werden:

ALTER VIEW uptime RENAME COLUMN "?column?" TO uptime;
SELECT * FROM uptime;

       current_timestamp       |     uptime      
-------------------------------+-----------------
 2020-03-23 15:37:40.726516+03 | 04:19:05.535548


ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION

Die generierte Spalte der Tabelle kann jetzt normalisiert werden, dh der Ausdruck wird gelöscht, um ihn auszuwerten:

CREATE TABLE payments (
    id integer PRIMARY KEY,
    amount numeric(18,2),
    income_tax numeric(18,2) GENERATED ALWAYS AS (amount*0.13) STORED
);
INSERT INTO payments(id, amount) VALUES(1, 42);
\d payments

                                     Table "public.payments"
   Column   |     Type      | Collation | Nullable |                   Default            
        
------------+---------------+-----------+----------+--------------------------------------
 id         | integer       |           | not null |
 amount     | numeric(18,2) |           |          |
 income_tax | numeric(18,2) |           |          | generated always as ((amount * 0.13))
 stored
Indexes:
    "payments_pkey" PRIMARY KEY, btree (id)

Anschließend beschlossen sie, die Einkommenssteuer explizit festzulegen. Löschen Sie den Ausdruck:

ALTER TABLE payments ALTER COLUMN income_tax DROP EXPRESSION;
\d payments

                   Table "public.payments"
   Column   |     Type      | Collation | Nullable | Default
------------+---------------+-----------+----------+---------
 id         | integer       |           | not null |
 amount     | numeric(18,2) |           |          |
 income_tax | numeric(18,2) |           |          |
Indexes:
    "payments_pkey" PRIMARY KEY, btree (id)

Natürlich sind die vorhandenen Daten aus der Spalte nicht verschwunden:

SELECT * FROM payments;

 id | amount | income_tax
----+--------+------------
  1 |  42.00 |       5.46


DROP DATABASE ... FORCE
Wenn Sie für alle Benutzer zu trennenohnewarteneine Datenbank löschen möchten, können Sie den neuen verwendenFORCEBefehlOptionDROP DATABASE.

CREATE DATABASE db;

Stellen Sie eine Verbindung zur neuen Datenbank her:

CREATE EXTENSION IF NOT EXISTS dblink;
SELECT dblink_connect('dbname=db');

 dblink_connect
----------------
 OK

Und jetzt werden wir pg_terminate_backendoffene Verbindungen löschen und gewaltsam unterbrechen :

DROP DATABASE db WITH (FORCE);

ALTER TYPE ... SET STORAGE
Mit dem BefehlALTER TYPEkönnen grundlegende Datentypen verschiedene Eigenschaften ändern, insbesondere die Speicherstrategie. Bisher konnte man es nur in einem Team einstellenCREATE TYPE.

Zur Demonstration erstellen wir keinen neuen Basistyp, sondern verwenden den vorhandenen -tsquery. Erstellen Sie zunächst eine separate Datenbank und stellen Sie eine Verbindung dazu her:

CREATE DATABASE db;
\c db

Für den Datentyp tsquery wird eine Speicherstrategie verwendet plain, sodass Spalten von Tabellen dieses Typs dieselbe Strategie erhalten:

SELECT typname,typstorage FROM pg_type WHERE typname = 'tsquery';

 typname | typstorage
---------+------------
 tsquery | p

CREATE TABLE queries (query tsquery);
SELECT attname, attstorage FROM pg_attribute WHERE attrelid = 'queries'::regclass AND attname = 'query';

 attname | attstorage
---------+------------
 query   | p

Wenn Sie für neue Tabellen eine andere Strategie verwenden müssen, können Sie den Basistyp ändern:

ALTER TYPE tsquery SET (storage=external);
SELECT typname,typstorage FROM pg_type WHERE typname = 'tsquery';

 typname | typstorage
---------+------------
 tsquery | e

Die Art des Speichers in den neuen Tabellen ändert sich ebenfalls:

CREATE TABLE new_queries (query tsquery);
SELECT attname, attstorage FROM pg_attribute WHERE attrelid = 'new_queries'::regclass AND attname = 'query';

 attname | attstorage
---------+------------
 query   | e

Es sollte bedacht werden, dass eine Änderung einer Strategie, die den Einsatz von TOAST beinhaltet, plainnicht wieder geändert werden kann in :

ALTER TYPE tsquery SET (storage=plain);

ERROR:  cannot change type's storage to PLAIN

Daher wurden die Experimente in einer separaten Datenbank durchgeführt, was nicht zu löschen ist.

ALTER STATISTICS ... SET STATISTICS Mit dem

Befehl CREATE STATISTICSkönnen Sie Listen der häufigsten Werte für ausgewählte Kombinationen von Tabellenspalten erfassen. Die Anzahl der am häufigsten erfassten Werte wird durch den Parameter bestimmt default_statistics_target. Der Wert für bestimmte Statistiken kann jetzt mit dem folgenden Befehl geändert werden:

ALTER STATISTICS  SET STATISTICS _;

FETCH FIRST with WITH TIES-Option
Wie Sie wissen, können SieSELECTanstelle einesBefehlsLIMITdie im SQL-Standard definierte Syntax verwenden:

SELECT *
FROM (VALUES (1,'1.1'), (2,'2.1'), (2,'2.2'), (3,'3.1')) t(a,b)
ORDER BY a
FETCH FIRST 2 ROWS ONLY;

 a |  b  
---+-----
 1 | 1.1
 2 | 2.1
(2 rows)

Jetzt FETCHunterstützt es die Phrase WITH TIES, die der Ausgabe alle "verwandten" Zeilen hinzufügt (Zeilen, die den bereits ausgewählten entsprechen, wenn nur die Sortierbedingung berücksichtigt wird):

SELECT *
FROM (VALUES (1,'1.1'), (2,'2.1'), (2,'2.2'), (3,'3.1')) t(a,b)
ORDER BY a
FETCH FIRST 2 ROWS WITH TIES;

 a |  b  
---+-----
 1 | 1.1
 2 | 2.1
 2 | 2.2
(3 rows)

Integrierte Funktionen und Datentypen


get_random_uuid Die
neue Funktionget_random_uuidgibt den UUID-Wert der Version 4 (Zufallswert) zurück:

SELECT gen_random_uuid();

           gen_random_uuid            
--------------------------------------
 25e02793-80c0-438c-be07-c94b966c43ab

Die Funktion ist nützlich, um eindeutige UUID-Werte in verteilten Systemen zu generieren.
Zuvor mussten Sie die Bibliotheken uuid-ossp oder pgcrypto verwenden.

min_scale und trim_scale für Werte vom Typ numerisch

Die Funktion min_scalebestimmt die Anzahl der signifikanten Stellen im Bruchteil der Zahl, und die Funktion trim_scaleverwirft nicht signifikante Nullen:

SELECT n, min_scale(n), trim_scale(n) FROM (VALUES(42.42000)) as t(n);

    n     | min_scale | trim_scale
----------+-----------+------------
 42.42000 |         2 |      42.42

gcd und lcm

Nachschub im Abschnitt der mathematischen Funktionen. Jetzt können Sie schnell den größten gemeinsamen Teiler (gcm) und das kleinste gemeinsame Vielfache (lcm) finden:

SELECT gcd(54,24), lcm(54,24);

 gcd | lcm
-----+-----
   6 | 216

Aggregatfunktionen min und max für Typ pg_lsn Aggregatfunktionen wurden für den zusätzlichen

Datentypunddass können Sie Abfragen der Form auszuführen:pg_lsnminmax

SELECT min(restart_lsn) FROM pg_replication_slots;
SELECT min(sent_lsn) FROM pg_stat_replication;

Überprüfen des Typmodifikators des Rückgabewerts einer Funktion

In früheren Versionen wurde der Typmodifikator nicht auf den Rückgabewert der Funktion überprüft.

Angenommen, es gibt einen Typ zum Speichern von Geldeinheiten und eine Funktion, die den Betrag der Einkommensteuer zurückgibt:

CREATE TYPE currency AS (
    amount numeric(18,2),
    code   text
);
CREATE FUNCTION income_tax(quantity currency) RETURNS currency
    AS 'SELECT quantity.amount * 0.13, quantity.code' LANGUAGE SQL;

Wenn wir die Funktion aufrufen, erwarten wir zwei Dezimalstellen, jedoch vier. Auch explizites Casting nach einem Funktionsaufruf hilft nicht (dritte Spalte):

SELECT amount, code, amount::numeric(18,2)
FROM income_tax(ROW(42.42, ''))\gx

-[ RECORD 1 ]--
amount | 5.5146
code   | 
amount | 5.5146

In Version 13 ist das Ergebnis korrekt:

SELECT amount, code, amount::numeric(18,2)
FROM income_tax(ROW(42.42, ''))\gx

-[ RECORD 1 ]
amount | 5.51
code   | 
amount | 5.51

Die lokalisierten Namen in to_date () und to_timestamp ()

Funktionento_dateauchto_timestampgelerntdie lokalisierten Namen der Monate und Tage der Woche zu verstehen. Bisher konnten nur englische Namen verwendet werden:

SELECT to_date(', 24  2020', 'TMDay, DD TMMonth YYYY');

  to_date   
------------
 2020-03-24

normalisieren und IS NORMALISIERT

Um dem SQL-Standard zu entsprechen, wurde die Funktion normalize () hinzugefügt, um eine Unicode-Zeichenfolge zu normalisieren, und das Prädikat IS NORMALIZED, um zu überprüfen, ob eine Zeichenfolge normalisiert ist.

SELECT str, normalize(str, NFC) AS nfc,
       str IS NFC NORMALIZED AS is_nfc_normalized,
       normalize(str, NFKC) AS nfkc,
       str IS NFKC NORMALIZED AS is_nfkc_normalized
FROM (VALUES(U&'\0032\2075')) AS vals(str)\gx

-[ RECORD 1 ]------+---
str                | 2⁵
nfc                | 2⁵
is_nfc_normalized  | t
nfkc               | 25
is_nfkc_normalized | f

Lesen Sie mehr über UNICODE-Normalisierungsformulare.

Xid8-Typ und xid8_current () -Funktion für 64-Bit-Transaktionsnummern

Ein neuer xid8-Datentyp für 64-Bit-Transaktionsnummern wurde hinzugefügt. Aber nein, das bedeutet nicht, dass PostgreSQL auf 64-Bit-Transaktionen umgestellt hat: Alles funktioniert genau wie zuvor. Aber einige Funktionen geben einen neuen Typen, zum Beispiel, wird nun für die Verwendung anstelle der alten Funktionen empfohlen pg_current_xact_id txid_current, die zurück int8, und so weiter. N.

Neue polymorphe Datentypen anycompatible

Familientypen hinzugefügt anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange. Im Gegensatz zu Familientypen können Sie anyelementmit neuen Typen nicht genau dieselben, sondern tatsächlich kompatible Typen verwenden.

Im folgenden Beispiel die Funktionmaximumals Argumente definiert als anycompatibleübergeben integerund numeric. Der Rückgabewert wird für diese beiden Typen in einen gemeinsamen Wert konvertiert:

CREATE FUNCTION maximum(a anycompatible, b anycompatible) RETURNS anycompatible
	AS 'SELECT CASE WHEN a > b THEN a ELSE b END' LANGUAGE SQL;

SELECT f, pg_typeof(f) FROM maximum(42, 42.42) f;

   f   | pg_typeof
-------+-----------
 42.42 | numeric

Darüber hinaus sind die Typen anycompatible- und any- zwei unabhängige Artengruppen:

CREATE FUNCTION first_elems(a anyarray, b anycompatiblearray)
    RETURNS TABLE(a anyelement, b anycompatible) AS $$
        SELECT ROW(a[array_lower(a,1)], b[array_lower(b,1)]);
    $$ LANGUAGE sql;
SELECT first_elems(ARRAY[1,2,3], ARRAY['a','b','c']) AS str, 
       first_elems(ARRAY[1.1,2.2,3.3],ARRAY[true,false]) bool;

  str  |  bool   
-------+---------
 (1,a) | (1.1,t)

Verfahrenssprachen


Transformation für Typ bool in PL / Perl
Zuletzt wurde TRANSFORM von Ivan Panchenko (Postgres Professional) - bool_plperl festgeschrieben . Postgres übergibt boolesche Werte antoderin PL / Perl wief, aber für Perl ist esfkeinboolescher Wert false , sondern nur der Buchstabe f, d. H. in einem logischen Kontext die Wahrheit . Dieses Problem kann auf verschiedene Arten gelöst werden (siehe Korrespondenz ), aber laut Tom Lane ist es am praktischsten, TRANSFORM für bool zu erstellen.

Schnelle Ausführung einfacher Ausdrücke in PL / pgSQL

Einfache Ausdrücke (die zumindest keine Tabellenaufrufe enthalten und keine Sperren erfordern) sind schneller. Bisher wurde in diesen Fällen unproduktiv Zeit für die Kontaktaufnahme mit dem Scheduler in jedem Zyklus aufgewendet.

CREATE OR REPLACE FUNCTION slow_pi() RETURNS double precision AS $$
    DECLARE
        a double precision := 1;
        s double precision := 1;
        r double precision := 0;
    BEGIN
        FOR i IN 1 .. 10000000 LOOP
            r := r + s/a; a := a + 2; s := -s;
        END LOOP;
        RETURN 4*r;
    END;
    $$ LANGUAGE plpgsql;

Rufen Sie slow_pi () in PG12 auf:

SELECT slow_pi();

          slow_pi      
    --------------------
     3.1415925535898497
    (1 row)
    Time: 13060,650 ms (00:13,061)

Jetzt in PG13:
SELECT slow_pi();

          slow_pi      
    --------------------
     3.1415925535897915
    (1 row)
    Time: 2108,464 ms (00:02,108)

Vertrauenswürdige Erweiterungen anstelle von pg_pltemplate

Das Systemverzeichnis wurde um eine Tabelle verringert. Gelöschtpg_pltemplate. Es wurden die Eigenschaften von prozeduralen Sprachen gespeichert, die während der Ausführung benötigt werdenCREATE LANGUAGE. Jetzt haben wir beschlossen, die Eigenschaften in den Skripten der Erweiterungen der entsprechenden Sprachen zu registrierenpg_pltemplateund die Tabelle selbst zu entfernen. Um den Plan zu implementieren, muss dem Datenbankeigentümer (ohne Superuser-Rechte) die Möglichkeit eingeräumt werden, eine vertrauenswürdige Sprache aus dem Erweiterungsskript zu erstellen. Um beispielsweise beispielsweise plpgsql zu erstellen, muss der Datenbankeigentümer kein Superuser sein.

Wie folgt erhalten. In der Steuerdatei für Erweiterungen wurde ein neuer logischer Parameter angezeigttrusted. Wenn beide Parametertrustedundsuperuserenthalten, dann kann die Erweiterung nicht nur vom Superuser, sondern auch vom Benutzer mit dem Recht CREATEauf die aktuelle Datenbank (und damit deren Eigentümer) erstellt werden. Bei der Ausführung eines Skripts einer solchen Erweiterung werden die Superuser-Rechte verwendet, mit denen der Cluster initialisiert wurde. Die von der Erweiterung erstellten Objekte gehören dazu, obwohl der Eigentümer der Erweiterung selbst der erstellende Benutzer ist.

Wichtige Folgen dieser Änderungen:

  • Vertrauenswürdige Erweiterungen ermöglichen Drittentwicklern das Erstellen anderer vertrauenswürdiger Sprachen. Jetzt sind wir nur noch auf plpgsql, plperl und pltcl beschränkt.
  • Es pg_pltemplatewar schwer zu schreiben, dass sich plpython auf die zweite Version der Sprache bezieht. Andernfalls pg_pltemplateist ein Schritt (notwendig, aber nicht ausreichend) zum Übergang zu Python 3.

Indizes


Komprimierung des B-Baums
Ein wichtiger und lang erwarteter (die Arbeit begann bereits 2015) Patch, der von Anastasia Lubennikova (Postgres Professional) und Peter Geigan (Peter Geoghegan) geschrieben wurde, wird schließlich von Peter kommuniziert. Nastya hat es geschafft, auf der PGconf India darüber zu sprechen . Postgres hat gelernt, die Größe von B-Tree-Indizes durch Deduplizierung, dh Einsparungen bei doppelten Indexschlüsseln, erheblich zu reduzieren. Diese Indizes wurden grundlegend überarbeitet, sodass eine Komprimierung ohne Verlust der Kompatibilität mit früheren Indexversionen möglich ist. Die Idee der Deduplizierung basiert auf einer flexibleren Architektur von Indizes wie GIN (Reverse Indexes - Generalized Inverted Index).

In diesen Indizes häufiger als im B-BaumEs gibt eine Situation, in der ein Schlüssel einer großen Anzahl von Datensätzen entspricht. Beispielsweise wird bei der Textverarbeitung das gleiche Token normalerweise in mehreren Dokumenten gefunden. Und es wird nur einmal im Index gespeichert. Bis vor kurzem wussten B-Tree-Indizes nicht, wie das geht.

B-Tree-Indizes unterscheiden sich von GIN-Indizes hauptsächlich auf Blattseiten. Abhängig von der Anzahl der Datensätze, die sich auf denselben Schlüsselwert beziehen, sind Optionen möglich: Die Seite enthält nur eine Buchungsliste - eine Liste von TIDs (Kennungen von indizierten Datensätzen), wenn die Liste klein ist und wenn viele TIDs vorhanden sind, werden anstelle einer Liste von Werten gespeichert Neue „Baumzweige“ - Links zu anderen Seiten wie der Buchungsliste oder anderen Ästen (sie werden als Buchungsbaum bezeichnet).

Eine solche Baumstruktur ähnelt einem B-Baum, unterscheidet sich jedoch in wesentlichen Details: Beispielsweise sind Listen zum Durchblättern von Seiten derselben Baumebene in der GIN unidirektional und nicht bidirektional. Daher ist (einschließlich) eine gute Kompatibilität neuer, deduplizierter Indizes mit alten Versionen nicht einfach zu erreichen. Und die Verbesserungen haben wirklich mehr als 3 Jahre gedauert. Es war auch notwendig, den Reinigungsmechanismus (Mikrovakuum) und andere Nuancen zu erarbeiten.

In Leistungstests sind alle Indizes, für die die Deduplizierung gilt, um das Dreifache geschrumpft. Das Komprimieren von Duplikaten hilft auch bei eindeutigen Indizes, wodurch das Problem der Indexschwellung bei einer hohen Rate von Tabellenänderungen beseitigt wird. Neues Verhalten kann auf der Ebene der Indexeinstellungen verbunden und getrennt werden.

Ein vollständiger Scan nach GIN-Index wird nicht durchgeführt, wenn dies nicht erforderlich ist
Mit diesem Patch kann in einigen Fällen ein vollständiger Durchlauf des gesamten GIN-Index vermieden werden. Einige Vorgänge werden, obwohl sie vom GIN-Index unterstützt werden, durch einen vollständigen Scan des Index ausgeführt. Nehmen Sie zum Beispiel den Index für die Volltextspalten-Suche tsvector. Wenn die Suchabfrage die Form "alles andere als ein bestimmtes Wort" hat, muss der gesamte Index vollständig gelesen werden. Wenn jedoch eine andere Bedingung in der Anforderung vorhanden ist, die keinen vollständigen Scan des Index erfordert, wird der Index weiterhin vollständig gescannt.

Bei der neuen Optimierung wird zuerst eine genauere Bedingung verwendet, sodass Sie einen Gewinn aus dem Index ziehen können. Anschließend werden die Ergebnisse doppelt überprüft, um eine weitere Einschränkung zu berücksichtigen. Vergleichen Sie die Anzahl der Seiten, die in Version 12 (Puffer) gelesen wurden:

EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF)
SELECT * FROM mail_messages WHERE tsv @@ to_tsquery('!vacuum') AND tsv @@ to_tsquery('analyze');

                                             QUERY PLAN                                             
------------------------------------------------------------------
Bitmap Heap Scan on mail_messages (actual rows=5864 loops=1)
   Recheck Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
   Heap Blocks: exact=5167
   Buffers: shared hit=24 read=27405
   ->  Bitmap Index Scan on mail_messages_tsv_idx (actual rows=5864 loops=1)
         Index Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
         Buffers: shared hit=24 read=22238
 Planning Time: 0.283 ms
 Execution Time: 3258.234 ms

mit der Anzahl der Puffer in der neuen Version:

EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF)
SELECT * FROM mail_messages WHERE tsv @@ to_tsquery('!vacuum') AND tsv @@ to_tsquery('analyze');

                                             QUERY PLAN                                             
---------------------------------------------------------------------------
Bitmap Heap Scan on mail_messages (actual rows=5864 loops=1)
   Recheck Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
   Heap Blocks: exact=5156
   Buffers: shared hit=5179
   ->  Bitmap Index Scan on mail_messages_tsv_idx (actual rows=5864 loops=1)
         Index Cond: ((tsv @@ to_tsquery('!vacuum'::text)) AND (tsv @@ to_tsquery('analyze'::text)))
         Buffers: shared hit=23
 Planning Time: 0.250 ms
 Execution Time: 8.779 ms

Eine ähnliche Situation kann auftreten, wenn Trigramme verwendet werden und wenn das Auftreten von Arrays überprüft wird.

Parameter von Operatorklassen
In PostgreSQL sind viele Indexzugriffsmethoden ein „Framework“, das eine allgemeine Implementierung des Suchalgorithmus übernimmt und mit Seiten und Sperren sowie dem WAL-Protokoll arbeitet. Die Bindung an bestimmte Datentypen und Operatoren erfolgt mithilfe von Operatorklassen.

Bisher konnten Operatorklassen keine Parameter haben. Zum Beispiel für eine Volltextsuche, ein GiST Index mit einer Klasse von Operatoren kann verwendet werden tsvector_ops(über Klassen von GiST Betreibern hier) Diese Klasse von Operatoren verwendet einen Signaturbaum, und die Signaturlänge wurde festgelegt (124 Byte). Jetzt können Sie die Länge explizit angeben, wodurch Sie das Gleichgewicht zwischen der Größe des Index und der Effizienz (der Anzahl der Hash-Kollisionen) steuern können:

CREATE INDEX ON mail_messages USING gist(tsv tsvector_ops(siglen=1024));

Ähnliche Änderungen wurden für den Anfang für andere Klassen von GiST-Operatoren vorgenommen, die einen Signaturbaum verwenden, der für die Erweiterungen hstore, intarray, ltree und pg_trgm gilt.
Die Hauptidee, für die diese Änderung konzipiert wurde, ist die Möglichkeit, den JSONPath-Ausdruck an den GIN-Index zu übergeben, sodass nicht das gesamte JSON-Dokument indiziert wird, sondern nur der erforderliche Teil davon. In vielen Fällen wird dadurch die Größe der Indizes radikal reduziert. Diese Arbeit bleibt jedoch noch zu erledigen.

Die Idee von Oleg Bartunov, die Umsetzung von Nikita Glukhov und Alexander Korotkov (alle drei Postgres Professional).

Der Operator <-> (Feld, Punkt) wurde
hinzugefügt. Die fehlende Operation wurde zur Verwendung in kNN für GiST und SP-GiST hinzugefügt . In PG12 beim Arbeiten mit geometrischen Typen pointundboxSie können den Entfernungsoperator verwenden, der <->(point, box)die Suche mit den Indizes GiST und SP-GiST beschleunigt. Der für ihn symmetrische Operator <->(box, point)wurde jedoch nicht implementiert, obwohl er boxdie Abstände zu komplexeren Typen - Polygonen und Kreisen - bereits verstand.

CREATE TABLE points(point point);
CREATE TABLE boxes(box box);
INSERT INTO points VALUES('1,2','3,4');
INSERT INTO boxes VALUES(box(point(3,4),point(5,6)), box(point(13,14),point(15,16)));

In PG12:
SELECT p.point, b.box, b.box  <-> p.point distance FROM points AS p, boxes AS b ORDER BY distance;

:    : box <-> point

Wenn umgekehrt, dann ist alles in Ordnung:

SELECT p.point, b.box, p.point  <-> b.box distance FROM points AS p, boxes AS b ORDER BY distance;

 point |       box       |      distance
-------+-----------------+--------------------
 (1,2) | (5,6),(3,4)     | 2.8284271247461903
 (2,1) | (5,6),(3,4)     | 3.1622776601683795
 (1,2) | (15,16),(13,14) | 16.970562748477143
 (2,1) | (15,16),(13,14) | 17.029386365926403

Und in PG13:

SELECT p.point, b.box, b.box  <-> p.point distance FROM points AS p, boxes AS b ORDER BY distance;

 point |       box       |      distance
-------+-----------------+--------------------
 (1,2) | (5,6),(3,4)     | 2.8284271247461903
 (2,1) | (5,6),(3,4)     | 3.1622776601683795
 (1,2) | (15,16),(13,14) | 16.970562748477143
 (2,1) | (15,16),(13,14) | 17.029386365926403

GiST- und SP-GiST-Indizes werden bei dieser Operation beschleunigt.

Beachten Sie, dass in PG13, wenn Sie fragen:

SELECT count(*) FROM pg_operator WHERE oprname = '<->';
 count 
-------
    28

und wenn wir dasselbe in PG12 tun, erhalten wir 20 Einträge: In der 13. Version wurde die Liste mit bis zu 8 Operatoren aufgefüllt.

Json


Unterstützung für die .datetime () -Methode für jsonpath

Dies ist einer der erfolglosen Patches einer großen Reihe von JSONPath-Patches, für deren Abschluss PG12 keine Zeit hatte. Teil des JSON / SQL-Standards. Das Problem war, dass alle Funktionen in der JSONPath-Patch-Serie unveränderlich sind, der Datumsvergleich jedoch die aktuelle Zeitzone berücksichtigt, die sich während der Sitzung ändern kann.

In solchen Fällen erlauben wir vorhandenen unveränderlichen Funktionen, einen Fehler bei nicht unveränderlichen Vergleichen auszulösen. Gleichzeitig verfügt dieser Patch über Funktionen mit dem Suffix _tz, die bei Operationen mit Zeitzone stabil funktionieren.

Neue Funktion - jsonb_set_lax Funktion

Im Allgemeinen ist lax eine nicht strenge (im Gegensatz zu strengen) Funktionsweise von Funktionen mit jsonb. In diesem Fall ist diese Funktion in einer Situation funktionsfähig, in der eines der Argumente NULL ist. Im Gegensatz zur strengen Version - jsonb_set () - gibt es ein zusätzliches Argument, das Aktionen im Fall von NULL angibt. Optionen: use_json_null / raise_exception / return_target / delete_key. Von interessierten Benutzern vorgeschlagene Optionen.

Einige jsonb-Funktionen wurden

optimiert. Viel optimiert ., hauptsächlich durch die Bemühungen von Nikita Glukhov (Postgres Professional). Aber jeden Punkt in diesem Fall zu analysieren ist sinnlos: Erstens wird ihre Fülle einen bereits kurzen Artikel aufblasen; und zweitens beziehen sich die Änderungen auf das interne Gerät, und nicht jeder Benutzer ist interessiert. Daher werden wir nur die meisten auflisten:

  1. Optimierte Funktion JsonbExtractScalar ();
  2. Optimierter Operator # >>, Funktionen jsonb_each_text (), jsonb_array_elements_text ();
  3. Die Erkennung des Typs JsonbContainer in get_jsonb_path_all () ist optimiert.
  4. Das Abrufen des ersten Tokens vom JsonbIterator-Iterator wird durch das einfache Makro JsonbContainerIsXxx () ersetzt.
  5. Bequemere Schlüsselextraktion - findJsonbKeyInObject ();
  6. Optimierte Speicherung der Ergebnisse findJsonbValueFromContainer () und getIthJsonbValueFromContainer ();
  7. get_jsonb_path_all(), ;
    JsonbValueAsText.

, SQL/JSON: JSON_TABLE SQL/JSON: functions. . , . . PG14. JSONPath .


pgbench


Das Dienstprogramm zum Ausführen von Leistungstests erhielt eine Reihe von Verbesserungen. Es gab Statistiken über die Ausführung von Aufgaben in der Initialisierungsphase, eine visuellere Schlussfolgerung , die Möglichkeit, den Code integrierter Skripte anzuzeigen und Tests an einer partitionierten Kontenliste durchzuführen.

Darüber hinaus haben wir einen \asetähnlichen Befehl hinzugefügt \gset, der jedoch das Festlegen von Werten für Variablen mehrerer gleichzeitig gesendeter Anforderungen ermöglicht. Die folgende Zeile, die zur Ausführung an den Server gesendet wird, legt beide Variablen oneund fest two:
SELECT 1 AS one \; SELECT 2 AS two \aset

pg_dump


pg_dump hat gelernt, Daten aus Tabellen von Drittanbietern zu entladen . Über den Parameter können --include-foreign-dataSie eine Liste von Servern von Drittanbietern angeben, deren Daten aus den Tabellen entladen werden.

Gehen Sie beim Entladen vorsichtig vor. Weit davon entfernt, dass die Daten auf einen Drittanbieter-Server hochgeladen werden müssen. Darüber hinaus ist es durchaus möglich, dass während der Wiederherstellung kein Server eines Drittanbieters verfügbar ist. Oder ein Server eines Drittanbieters kann nur das Lesen, aber nicht das Schreiben von Daten zulassen.

psql


Eine Reihe kleiner Patches macht psql komfortabler:

  • Verbesserte Tab-Vervollständigung für mehrere Teams.
  • Zusätzlich zum \echoSenden einer Zeichenfolge an STDOUT \warnsendet ein neuer Befehl eine Zeichenfolge an die Standardfehlerausgabe (STDERR).
  • \d toast- . \d+ .
  • \dt+ «Persistence» (unlogged) (permanent).
  • \e , ; ( \g*). , psql .
  • . PROMPT1 PROMPT2 %x.
  • Neue Befehle für weitere Informationen über Zugriffsmethoden: \dAc, \dAf, \dAo,\dAp
  • Sie können\g jetzt in Klammern alle unterstützten Optionen angeben\pset . Sie werden nur im aktuellen Team agieren.


libpq


Kleinere Änderungen im Zusammenhang mit PostgreSQL:
  • Die Ungenauigkeit in der Beschreibung der Host- und Hostadr-Parameter und die daraus resultierende Inkonsistenz in der Ausgabe des \conninfoDienstprogrammbefehls psql wurden behoben.
  • Wenn der Client-Zertifikatschlüssel verschlüsselt gespeichert ist, können Sie das Kennwort nur im interaktiven Modus eingeben. Mit dem neuen Parameter sslpassword können Sie den Schlüssel nicht interaktiv entschlüsseln.
  • Mit zwei neuen Parametern, sslminprotocolversion und sslmaxprotocolversion, können Sie eine Einschränkung für die Version des SSL / TCL-Protokolls festlegen, mit der die Verbindung zulässig ist.

reindexdb


Der neue Parameter --jobs des Dienstprogramms reindexdb legt die Anzahl der Datenbankverbindungen fest, in denen Indizes gleichzeitig neu erstellt werden.

pg_rewind


Die Einschränkungen des Dienstprogramms werden allmählich aufgehoben, und die Möglichkeiten nehmen zu.
Erstens kann pg_rewind jetzt Informationen für die Wiederherstellung aufzeichnen (wie pg_basebackup dies kann) sowie die Wiederherstellung und das anschließende Herunterfahren einer Instanz starten, wenn sie nicht über einen Prüfpunkt gestoppt wurde (dies musste zuvor manuell erfolgen).

Und zweitens hat pg_rewind gelernt, mit dem WAL-Archiv zu arbeiten .
Nachdem das Dienstprogramm den WAL-Divergenzpunkt zwischen den beiden Servern gefunden hat, sollte es eine Liste aller Seiten erstellen, die in den Zielcluster kopiert werden müssen, um die Unterschiede zu beseitigen. Dazu benötigt das Dienstprogramm alle WAL-Dateien ab dem gefundenen Punkt. Wenn die erforderlichen WAL-Dateien im Zielcluster nicht verfügbar sind, konnte das Dienstprogramm seine Arbeit zuvor nicht ausführen.

Mit diesem Patch von Alexey Kondratov (Postgres Professional) kann pg_rewind die fehlenden WAL-Segmente aus dem Archiv der Protokolldateien mithilfe des Parameters restore_command lesen, wenn ein neuer Schalter -c oder --restore-target-wal angegeben wird.

pg_waldump


pg_waldump entschlüsselt den vorbereiteten Transaktionsdatensatz.

amcheck


Die Amcheck-Erweiterung hat gelernt, Schäden in B-Tree-Indizes besser zu erkennen .
Übrigens unterscheiden sich Nachrichten im Serverprotokoll über beschädigte Seiten für Indizes und Tabellen .

pageinspect


Die heap_tuple_infomask_flagspageinspect-Erweiterungsfunktion entschlüsselt die Werte der Felder infomask und gibt sie infomask2von der Funktion zurück heap_page_items. Nützlich bei der Untersuchung von Datenkorruptionssituationen.

postgres_fdw


Der Superuser auf der Ebene der Benutzernamenzuordnung kann regulären Benutzern ermöglichen , eine Verbindung ohne Kennwort zu verwenden:

ALTER USER MAPPING FOR  SERVER 
    OPTIONS (ADD password_required 'false');

Dies geschieht unter anderem, damit sslkey und sslcert als Verbindungsparameter verwendet werden können .

adminpack


Die Adminpack-Erweiterung hat eine neue Funktion - pg_file_sync. Mit dieser Funktion können Sie fsync für Dateien ausführen, die vom Server auf die Festplatte geschrieben wurden, z. B. über pg_file_writeoder COPY TO.

Überwachung


pg_stat_slru


Im gemeinsam genutzten Speicher des Servers befindet sich nicht nur ein großer Puffercache, sondern auch eine Reihe anderer, einfacherer Caches (z. B. für den Transaktionsstatus). Sie verwenden einen einfachen Algorithmus zum Verdrängen der am seltensten verwendeten Seiten (einfache, am wenigsten kürzlich verwendete oder SLRU). Bisher haben solche Caches „nur funktioniert“, aber sie mussten zunächst überwacht werden, damit die Entwickler des PostgreSQL-Kernels herausfinden konnten, ob in ihnen etwas geändert werden muss. Zu diesem Zweck wurde eine neue Ansicht von pg_stat_slru angezeigt .

pg_stat_activity


In der Ansicht, die pg_stat_activity neue Spalte ist leader_id. Für Prozesse, die an parallelen Anforderungen teilnehmen, wird die Nummer des führenden Prozesses angegeben. Und führender Prozess leader_idist eine Prozessnummer pid.
Die folgende Abfrage zeigt, welche Abfragen und welche Prozesse derzeit parallel ausgeführt werden:

SELECT query, leader_pid, 
    array_agg(pid) filter(WHERE leader_pid != pid) AS members
  FROM pg_stat_activity
 WHERE leader_pid IS NOT NULL
 GROUP BY query, leader_pid;

Es gibt Änderungen an der Liste der wartenden Ereignisse. Zwei neue Ereignisse hinzugefügt : BackupWaitWalArchiveund RecoveryPause. Und die anderen beiden erhielten genauere Namen: RecoveryWalStream -> RecoveryRetrieveRetryInterval, RecoveryWalAll -> RecoveryWalStream.

Und zwei weitere neueRecoveryConflictSnapshot Warteereignisse, die auf dem Replikat auftreten : (Konflikt mit VACUUM, wodurch die erforderliche Version der Zeilen gelöscht wurde) und RecoveryConflictTablespace(Konflikt im Zusammenhang mit dem Entfernen des Tabellenbereichs).

pg_stat_statements


Bisher hat die Erweiterung pg_stat_statementsAnfragen mit FOR UPDATEund ohne Phrase als dieselbe Anfrage behandelt. Jetzt werden Anfragen mit FOR UPDATE separat erfasst .

Die Menge der gesammelten Informationen hat zugenommen. Von nun an werden nicht nur Informationen zu Ressourcen für die Ausführung von Befehlen aufgezeichnet, sondern auch Statistiken zu generierten Journaleinträgen . Neue Präsentationsspalten: wal_bytes- Volumen der generierten Datensätze, wal_records- Anzahl der generierten Datensätze, wal_num_fpw- Anzahl der ganzseitigen Bilder (ganzseitige Schreibvorgänge).

Möglich wurde dies durch die vorbereitete Infrastruktur zur Verfolgung der Nutzung von WAL. Daher wird jetzt EXPLAINmit einer neuen Option WALdas Volumen der generierten Datensätze angezeigt:

CREATE TABLE t (id int);
EXPLAIN (ANALYZE, WAL, COSTS OFF, TIMING OFF, SUMMARY OFF)
    INSERT INTO t VALUES(1);

              QUERY PLAN              
--------------------------------------
 Insert on t (actual rows=0 loops=1)
   WAL:  records=1  bytes=59
   ->  Result (actual rows=1 loops=1)

Erweiterung auto_explain, VACUUMs VERBOSE, und verwenden Sie autovacuumauch die erstellte Infrastruktur und geben Sie Volumina von WAL aus.

Zurück zu pg_stat_statements. Wenn der neue Parameter pg_stat_statements.track_planning aktiviert ist , werden für jeden Operator zusätzliche Statistiken zum Scheduler aufgezeichnet: Anzahl der Planerstellungen; Gesamtplanungszeit; minimale und maximale Zeit einer Planung sowie Mittelwert und Standardabweichung.

Die Berücksichtigung der dem Scheduler zugewiesenen Ressourcen spiegelt sich in einem anderen Patch wider, der nicht in Beziehung steht pg_stat_statements. EXPLAINMit dieser Option BUFFERSwird die Anzahl der in der Planungsphase verwendeten Puffer angezeigt :

EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF) 
    SELECT * FROM pg_class;

                   QUERY PLAN                   
------------------------------------------------
 Seq Scan on pg_class (actual rows=386 loops=1)
   Buffers: shared hit=9 read=4
 Planning Time: 0.782 ms
   Buffers: shared hit=103 read=11
 Execution Time: 0.219 ms

Zeitschrift


  • log_statement_sample_rate SQL, , log_min_duration_sample( ).
    , log_min_duration_statement , .. log_min_duration_statement , log_min_duration_sample, , log_statement_sample_rate.
    , log_transaction_sample_rate , , .
  • , ( log_min_error_statement), . log_parameter_max_length_on_error. 0, .
    log_parameter_max_length_on_error SQL, , .
    ( log_statements log_duration) , : log_parameter_max_length, , .
  • Sie können jetzt den Prozesstyp ( pg_stat_activity.backend_type) in das Serverprotokoll schreiben . Hierzu log_line_prefixist im Parameter ein spezielles Symbol vorgesehen %b. Und wenn das Protokoll im csv ( log_destination=csvlog) -Format geschrieben ist , ist die Spalte dort backend_typebereits enthalten.


Fortschritt


Neue Ansichten pg_stat_progress_analyzeauch pg_stat_progress_basebackupermöglicht es Ihnen , den Fortschritt zu verfolgen Statistikerfassung durch das Team ANALYZEund eine Sicherungskopie des erstellen Dienstprogramm, pg_basebackupjeweils.

Optimierung


Berechnung unveränderlicher Funktionen in der FROM-Klausel in der Planungsphase
Der Patch von Aleksandr Kuzmenkov und Aleksandr Parfyonov (beide von Postgres Professional) hilft in Fällen, in denen derFROMAufruf einen Funktionsaufruf enthält, der tatsächlich eine Konstante ist. In diesem Fall wird anstelle der Verbindung der konstante Wert an den erforderlichen Stellen der Anforderung ersetzt.

So geschieht dies anhand eines Beispiels für eine Abfrage im Zusammenhang mit der Volltextsuche:

EXPLAIN (COSTS OFF)
SELECT subject, ts_rank_cd(tsv, q) AS rank
FROM mail_messages, to_tsquery('english', 'tuple') q
WHERE tsv @@ q
ORDER BY rank DESC;

                              QUERY PLAN                              
------------------------------------------------------------------
 Sort
   Sort Key: (ts_rank_cd(mail_messages.tsv, '''tuple'''::tsquery)) DESC
   ->  Bitmap Heap Scan on mail_messages
         Recheck Cond: (tsv @@ '''tuple'''::tsquery)
         ->  Bitmap Index Scan on mail_messages_tsv_idx
               Index Cond: (tsv @@ '''tuple'''::tsquery)

Es besteht keine Verbindung, und der Wert 'tuple' :: tsquery wird in der Abfrage bereits in der Planungsphase ersetzt. Version 12 hatte ein ganz anderes Bild:

EXPLAIN (COSTS OFF)
SELECT subject, ts_rank_cd(tsv, q) AS rank                            
FROM mail_messages, to_tsquery('english', 'tuple') q
WHERE tsv @@ q                            
ORDER BY rank DESC;

                          QUERY PLAN                         
-----------------------------------------------------
 Sort
   Sort Key: (ts_rank_cd(mail_messages.tsv, q.q)) DESC
   ->  Nested Loop
         ->  Function Scan on q
         ->  Bitmap Heap Scan on mail_messages
               Recheck Cond: (tsv @@ q.q)
               ->  Bitmap Index Scan on mail_messages_tsv_idx
                     Index Cond: (tsv @@ q.q)


Inkrementelle Sortierung

Wenn nach vielen Schlüsseln sortiert werden muss (k1, k2, k3 ...), kann der Scheduler jetzt das Wissen nutzen, dass die Daten bereits nach mehreren der ersten Schlüssel (z. B. k1 und k2) sortiert sind. In diesem Fall können Sie nicht alle Daten erneut sortieren, sondern sie in aufeinanderfolgende Gruppen mit denselben Werten k1 und k2 unterteilen und nach dem Schlüssel k3 „sortieren“.

Somit wird die gesamte Sortierung in mehrere aufeinanderfolgende Arten kleinerer Größe aufgeteilt. Dies reduziert den Speicherbedarf und ermöglicht es Ihnen, die ersten Daten auszugeben, bevor die Sortierung abgeschlossen ist.

In der Demobase in der Tickets-Tabelle befindet sich beispielsweise ein Index für die Spalte ticket_id. Vom Index empfangene Daten werden nach ticket_id sortiert, sodass bei der folgenden Abfrage eine inkrementelle Sortierung verwendet wird:

EXPLAIN (analyze, costs off, timing off)
SELECT * FROM tickets ORDER BY ticket_no, passenger_id;

                                  QUERY PLAN                                  
------------------------------------------------------------------------------
 Incremental Sort (actual rows=2949857 loops=1)
   Sort Key: ticket_no, passenger_id
   Presorted Key: ticket_no
   Full-sort Groups: 92184 Sort Method: quicksort Memory: avg=31kB peak=31kB
   ->  Index Scan using tickets_pkey on tickets (actual rows=2949857 loops=1)
 Planning Time: 2.137 ms
 Execution Time: 2230.019 ms

Inkrementelle Sortierfunktionen können mit dem Parameter enable_incrementalsort deaktiviert werden. In diesem Fall dauert das Sortieren merklich länger:

SET enable_incrementalsort = off;
EXPLAIN (analyze, costs off, timing off)
SELECT * FROM tickets ORDER BY ticket_no, passenger_id;

                              QUERY PLAN                               
-----------------------------------------------------------------------
 Gather Merge (actual rows=2949857 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Sort (actual rows=983286 loops=3)
         Sort Key: ticket_no, passenger_id
         Sort Method: external merge  Disk: 107024kB
         Worker 0:  Sort Method: external merge  Disk: 116744kB
         Worker 1:  Sort Method: external merge  Disk: 107200kB
         ->  Parallel Seq Scan on tickets (actual rows=983286 loops=3)
 Planning Time: 3.994 ms
 Execution Time: 12291.844 ms

Die Idee der inkrementellen Sortierung wurde bereits 2013 von Alexander Korotkov (Postgres Professional) vorgeschlagen, und jetzt, sieben Jahre später, wurde der Patch von James Coleman in einen von der Gemeinde akzeptierten Zustand gebracht.

TRUNCATE-Beschleunigung
Beim TRUNCATEScannen werden shared_buffersTabellenpuffer aus dem gemeinsam genutzten Speicher entfernt. Zuvor wurde für jede Tabellenebene dreimal gescannt: MAIN (Hauptdatenschicht), FSM (Freiraumkarte), VM (Sichtbarkeitskarte). Jetzt hat sich die Logik geändert. Statt einer Dreifachoperation werden die Puffer nur einmal gescannt. Bei großen Werten shared_buffersergibt sich ein spürbarer Gewinn.

Teildekompression TOAST
Wenn es nicht erforderlich ist, TOAST vollständig zu lesen und es auf ein Slice am Anfang oder nahe am Anfang zu beschränken, ist es nicht sinnvoll, es vollständig zu lösen. Komprimierter TOAST wird in Iterationen gelesen: Lesen Sie ein Stück, wenn keine erforderlichen Daten vorhanden sind, erweitern Sie es und lesen Sie weiter. Vorgeschlagen von einem Google Summer of Code-Studenten, Binguo Bao, der ein Beispiel gibt:

CREATE TABLE slicingtest (
     id serial PRIMARY KEY,
     a text
);
INSERT INTO slicingtest (a) SELECT
    repeat('1234567890-=abcdefghijklmnopqrstuvwxyz', 1000000) AS a FROM
    generate_series(1,100);
\timing
SELECT sum(length(substr(a, 0, 20))) FROM slicingtest;

Time: 28.123 ms

Mit dem Patch eine Größenordnung schneller:

Time: 2.306 ms

Paralleles VAKUUM
In seinem Artikel zu diesem Thema erklärt Jegor Rogow diesen wichtigen Schritt der Parallelisierung ausführlich. Kurzum: „Patch Masahiko Sawada, mit dem Sie die Reinigung parallel durchführen können. Die Tabelle selbst wird weiterhin von einem (führenden) Prozess gelöscht. Zum Bereinigen von Indizes können jetzt Hintergrundworkflows gestartet werden, einer für jeden Index. Im manuellen Modus können Sie so die Bereinigung großer Tabellen mit mehreren Indizes beschleunigen. Die automatische Reinigung nutzt diese Funktion noch nicht. “

Automatische Reinigung beim Einfügen in eine Tabelle
Für diesen Patch (auch als Berserker Auto-Vakuum bekannt) müssen wir uns bei Dorofei Proleskovsky bedanken, der eine Lösung für das folgende Problem vorgeschlagen hat: Die automatische Reinigung wird nicht in die Tabelle nur zum Anhängen aufgenommen, da sie keine "toten" Versionen der Zeilen enthält. Aus diesem Grund wird die Sichtbarkeitskarte nicht aktualisiert, sodass nur Index-Scans unwirksam werden. Wenn eine Bereinigung erfolgt, um ein Überlaufen des Transaktionszählers zu verhindern, muss viel Arbeit auf einmal erledigt werden. Jetzt wurde diese Situation behoben: Die automatische Reinigung funktioniert auch beim Hinzufügen von Zeilen. Es wurden zwei neue Serverparameter ( autovacuum_vacuum_insert_thresholdund autovacuum_vacuum_insert_scale_factor) angezeigt, ähnlich denen für Änderungen ( autovacuum_vacuum_thresholdund autovacuum_vacuum_scale_factor).

Hash Aggregate Memory Management
Die Hash-Aggregation erfordert möglicherweise mehr RAM als vom Scheduler angenommen und als in angegeben work_mem. Zuvor führte ein solcher Scheduler-Fehler dazu, dass die Größe work_memignoriert wurde und so viel Speicher zugewiesen wurde, wie für den Betrieb oder die Ankunft von OOM Killer erforderlich war. Jetzt geht der Algorithmus möglicherweise nicht darüber hinaus work_memund verwendet bei Bedarf temporäre Dateien auf der Festplatte. Um das Verhalten des Schedulers zu steuern, wurden die folgenden Parameter angezeigt: enable_groupingsets_hash_diskund enable_hashagg_disk.

UPDATE für Tabellen mit generierten Spalten optimieren
In Version 12 wurden die generierten Spalten während einer Zeilenaktualisierung neu berechnet, auch wenn diese Änderung sie in keiner Weise beeinflusste. Jetzt werden sie nur dann neu berechnet, wenn sie wirklich benötigt werden (wenn sich ihre Basisspalten geändert haben).

Diese Optimierung kann beispielsweise die Aktualisierung von Tabellen mit einer generierten Typspalte erheblich beschleunigen tsvector, da die Funktion to_tsvector()recht teuer ist.

Zugriff vom Trigger auf die Liste der geänderten Spalten
Ein kleiner Patch, TriggerDatader der Struktur eine Bitmap der geänderten Spalten hinzufügt . Diese Informationen können von allgemeinen Triggerfunktionen wie tsvector_update_trigger()oder verwendet werden lo_manage(), um keine unnötigen Arbeiten auszuführen.

Verwendung mehrerer erweiterter Statistiken bei der Auswertung
In PG12 konnte der Scheduler nicht mehrere erweiterte Statistiken für dieselbe Tabelle gleichzeitig verwenden. Stellen Sie sich beispielsweise eine Situation vor, in der zwei erweiterte Statistiken für verschiedene Spaltengruppen erstellt werden und Spalten aus einer Gruppe und einer anderen an der Abfrage teilnehmen. Jetzt hat der Planer Zugriff auf alle verfügbaren Informationen.

Infrastruktur für Parallelisierung und KOPIEREN (siehe auch diesen Patch. )
Die PostgreSQL-Parallelität funktioniert weiterhin für schreibgeschützte Abfragen. Es gibt Schwierigkeiten mit Autoren, und eine davon blockiert Prozesse, die gleichzeitig eine Aufgabe ausführen (in einer gemeinsamen parallelen Gruppe enthalten). Es wird angenommen, dass die Sperren solcher Prozesse nicht in Konflikt stehen. Beispielsweise können mehrere Prozesse eine exklusive Sperre für dieselbe Tabelle enthalten. Dies erfordert besondere Sorgfalt von den Kernel-Entwicklern, aber sonst würden sie ständig Deadlocks haben.
Es gibt jedoch zwei Ausnahmen:

  • Beziehungserweiterungssperre, die erfasst wird, wenn neue Seiten am Ende der Datendatei hinzugefügt werden, und
  • Seitensperre, die verwendet wird, wenn GIN-Indexelemente von der Warteliste in den Hauptbaum verschoben werden.

(Weitere Informationen finden Sie in diesem Artikel. )
Solche Sperren sollten auch zwischen Prozessen derselben parallelen Gruppe in Konflikt stehen - wodurch dieser Patch implementiert wird. Diese Sperren können jedoch niemals zu Deadlocks führen, sodass sie vom Scan ausgeschlossen werden.

Für den Benutzer ändert sich im Allgemeinen nichts, aber dieser Patch ist wichtig, da er zum einen den Weg für paralleles INSERT und COPY ebnet und zum anderen einen der PostgreSQL-Engpässe unter Hochlastbedingungen beseitigt (was im Bericht zu hören ist) HL ++ ).

Sicherheit


SKH PRH-
Primzahlen ersetzt Ersetzte EDH-Primzahlen (Diffie-Hellman Ephemeral Keys) unter Verwendung des jetzt nicht mehr gültigen SKIP-Protokolls.

initdb: Die Standardeinstellungen für die Authentifizierung
haben sich geändert. Die Standardzugriffseinstellungen für lokale und Netzwerkverbindungen haben sich beim Start von initdb geändert. Jetzt inpg_hba.conffür lokale Verbindungen anstelle des Authentifizierungsmethodetrustwirdpeer(oder md5wenn Peernicht unterstützt), undmd5für Netzwerkverbindungen. Zunächst wurden liberalere Maßnahmen diskutiert: Warnung in der Dokumentation. Dann härter :scram-sha-256. Infolgedessen haben wir uns entschlossen, uns aufpeerund zu beschränkenmd5.

Verwenden von explizit_bzero
Wichtiger Patch. Die Betriebssystemfunktionen bzero () und explic_bzero () schreiben Bytes, die enthalten, in die angegebenen Speicherbereiche '\0'(siehe z. B. Linux). Diese Patches sind nur der Anfang: Es gibt viele Speicherbereiche, in denen Kennwörter und andere vertrauliche Informationen verbleiben können. Wir haben uns entschieden, an Orten wie libpq zu beginnen, an denen die gesamte Datei mit Passwörtern nach dem Lesen von .pgpass im Speicher verbleiben kann, und nach dem Schließen der Verbindung zu bereinigen. In be-secure-common.c wird jetzt die eingegebene geheime Phrase in SSL überschrieben, die in der Zeile (dem Pfad) des Fehlers angezeigt wird.

Der Parameter "password_protocol" wurde zu libpq hinzugefügt
Mit diesem Patch kann libpq steuern, welches Kennwortübertragungsprotokoll während der Verbindung verwendet wird. Nach Erhalt dieses Parameters verweigert libpq die Authentifizierung, wenn das Protokoll schwächer als das angegebene ist. Standardmäßig ist dieser Parameter plaintext, dh alle Protokolle, geeignet.

Obligatorischer Zugriff für TRUNCATE Mit
diesem Patch können Erweiterungen die obligatorische Zugriffssteuerung (MAC) für einen TRUNCATE-Vorgang einbetten. Die Rechte daran werden nun von der Erweiterung sepgsql überprüft . SELinux-Referenzrichtlinien und Redhat-basierte Linux-Distributionen unterstützen die SELinux-Überprüfung von db_table {truncate} nicht. In diesem Fall wird sepgsql mit 'leugnen_unknown' gleich 1 verwendet, und TRUNCATE schlägt fehl.

Verfügbarkeit von GUC ssl_passphrase_command
Ein einfacher, aber nützlicher Patch. Jetzt wird der Wert des Parameters ssl_passphrase_command nur vom Superuser angezeigt. Der Parameter gibt einen externen Befehl an, der aufgerufen wird, wenn zum Entschlüsseln einer SSL-Datei ein Kennwort erforderlich ist, z. B. ein privater Schlüssel.

Lokalisierung


Versionierung libc-Kollatierungsregeln
Bei ICU-Kollatierungsregeln werden Versionsnummern in der Datenbank gespeichert. Jedes Mal, wenn die Regel verwendet wird (Sortierung, Zeichenvergleich), wird die gespeicherte Versionsnummer mit der aktuellen Version in der ICU-Bibliothek im Betriebssystem überprüft, und bei Unstimmigkeiten wird eine Warnung ausgegeben. Auf diese Weise können Sie feststellen, dass bestimmte Indizes, die gemäß den geänderten Sortierregeln erstellt wurden, möglicherweise falsch sind und neu erstellt werden sollten. Durch die Neuerstellung der Indizes mit dem BefehlALTER COLLATION ... REFRESH VERSIONwird die Version der Sortierregel in der Datenbank aktualisiert und es werden keine Warnungen mehr ausgegeben.

Das war aber nur für die Intensivstation. Jetzt wird die Versionsnummer auch für libc-Sortierregeln gespeichert:

SELECT collname, collversion FROM pg_collation WHERE collname = 'ru_RU';

 collname | collversion
----------+-------------
 ru_RU    | 2.27

Dadurch können Warnungen ausgegeben werden, wenn sich eine Bibliothek im Betriebssystem ändert. Sehr relevant im Hinblick auf den Übergang zu glibc 2.28, wo sich viele Sortierregeln geändert haben und die entsprechenden Indizes neu erstellt werden sollten.

Aber bis sie auf 2.28 umgestiegen sind, ist alles ruhig:
ALTER COLLATION "ru_RU" REFRESH VERSION;

NOTICE:  version has not changed
ALTER COLLATION

Volltextsuche


Volltextsuche nach griechischer Sprache
Keine Kommentare.

dict_int hat gelernt, mit absoluten Werten
umzugehen . Das dict_int-Vorlagenwörterbuch (auch bekannt als Erweiterung) hat die Möglichkeit hinzugefügt, das Zeichen von einer Zahl zu entfernen.


CREATE EXTENSION dict_int;
SELECT ts_lexize('intdict', '-123');

ts_lexize
-----------
 {-123}
(1 row)

ALTER TEXT SEARCH DICTIONARY intdict (ABSVAL = true);
SELECT ts_lexize('intdict', '-123');

ts_lexize
-----------
 {123}
(1 row)

Das heißt, diesmal wurde der Absolutwert erkannt.

Partitionierung


VOR
ZeilenauslösernBEFOREfür eine partitionierte TabelleIn Version 12 können Sie keine Zeilenauslöserfür eine partitionierte Tabelleerstellen. In separaten Abschnitten - bitte, aber nicht auf einmal auf dem gesamten Tisch. Jetzt wird einBEFORE FOR EACH ROWTrigger, der für eine partitionierte Tabelle erstellt wurde, automatisch vererbt und funktioniert für alle Abschnitte. Unter der Bedingung, dassUPDATEder Partitionsschlüssel nur innerhalb des aktuellen Abschnitts geändert werden kann, wenn ein Triggeraktiviert ist.

Unterstützung für partitionierte Tabellen bei der logischen Replikation
Bisher hat das Einfügen einer partitionierten Tabelle in eine Publikation einen Fehler verursacht:

CREATE PUBLICATION pub FOR TABLE p;

ERROR:  "p" is a partitioned table
DETAIL:  Adding partitioned tables to publications is not supported.
HINT:  You can add the table partitions individually.

Jetzt funktioniert es.

Verbesserter Section-JOIN-Algorithmus
Ab der 11. Version kann der Scheduler partitionierte Tabellen abschnittsweise verknüpfen, jedoch nur, wenn die Grenzen der Abschnitte genau übereinstimmen. Jetzt wurde der Algorithmus verbessert: Er funktioniert, wenn der Abschnitt einer Tabelle vollständig im Abschnitt einer anderen Tabelle enthalten ist, auch wenn ihre Größe nicht übereinstimmt (z. B. wenn eine Tabelle nach Tag und die andere nach Monat unterteilt ist). Der neue Algorithmus funktioniert für die Partitionierung nach Bereichen und Listen.

Sectional FULL OUTER JOIN Sectionalized Join
funktioniert jetzt für vollständige äußere Joins, die mit einer Phrase aufgezeichnet wurden USING.

Tableam


In diesem attraktiven und vielversprechenden, aber schwierigen Bereich gibt es keine radikalen Fortschritte in Bezug auf PostgreSQL 12. Es gibt keine vorgefertigten Plug-In-Speicher (wie z. B. zheapHeap), aber die Arbeit an der API wird fortgesetzt.

Eine höhere Abstraktionsebene bei der Bestimmung der Größe der Tabelle
Robert Haas hat den Code neu geschrieben und seine Architektur zugunsten abstrakter Ebenen geändert, um den Code in Zukunft nicht zu duplizieren. Dieses Stück bezieht sich auf estimate_rel_size- die Größe der Schichten (Gabeln) des Tisches.

Sie können Tabellenzugriffsmethoden mit relcache verwenden.
Dieser Patch erweitert die Speicherverwaltungsfunktionen von Tabellenzugriffsmethoden auf die Funktionen von Indexmethoden.

Tableam und TOAST
TOAST sind größtenteils für die Lagerung konzipiertheapDaher können Sie beim Erstellen neuer Tabellenzugriffsmethoden auf zwei Arten vorgehen: Entwicklern neuer Methoden helfen, TOAST-Datensätze einzufügen, zu aktualisieren und zu löschen, oder die Arbeit mit TOAST an Code unter Verwendung des traditionellen PostgreSQL-Speicherheaps delegieren. Eine Reihe von 5 Patches verwendet Tupel-Slots, um Einfüge- / Aktualisierungs- / Löschvorgänge zu implementieren, und kann denjenigen helfen, die in beide Richtungen gehen.

fsync


Behandlung von fsync-Fehlern in pg_receivewal und pg_recvlogical
Der Kampf gegen fsync () geht weiter. PostgreSQL ist der Ansicht, dass ein erfolgreicher Aufruf von fsync () bedeutet, dass alle Daten in der Datei auf die Festplatte geschrieben wurden. Dies geschieht jedoch nicht immer (betriebssystemabhängig) und kann zu Datenverlust führen. PG13 entschied, dass es notwendig war, sich mit den Versorgungsunternehmenpg_receivewalundzu befassenpg_recvlogical. Derzeit lautet das Standardverhalten wie folgt: Diese Dienstprogramme schreiben fsync-Fehler in die Protokolle, stellen die Verbindung wieder her und fahren fort, als wäre nichts passiert. Infolgedessen enthält die WAL Informationen zu Dateien, die erfolgreich kopiert wurden und die tatsächlich nicht korrekt auf die Festplatte geschrieben wurden. Es ist daher besser, das Dienstprogramm zu unterbrechen. Das Schicksal von pg_dump, pg_basebackup, pg_rewind und pg_checksums wurde ebenfalls diskutiert, hat sich aber bisher auf diese beiden beschränkt.

Schutz vor dem Setzen falscher Flags für fsync ()
Dieser Patch prüft, ob die Flags beim Empfang des Dateideskriptors für fsync () richtig gesetzt sind - Verzeichnisse sind nur zum Lesen geöffnet und Dateien zum Schreiben oder beides.

Sicherung und Replikation


Pause während der Wiederherstellung vor Erreichen des Wiederherstellungspunkts
Wenn die WALs während der Wiederherstellung beendet wurden, aberrecovery_target_timedieangegebenenicht erreichthaben,schließt der Server die Wiederherstellung ab und wechselt in den normalen Betriebsmodus. Jetzt wird es nicht so sein. Der Wiederherstellungsprozess wird angehalten, wie im Protokoll angegeben, und der Administrator hat die Möglichkeit, die fehlenden WAL-Segmente einzufügen und die Wiederherstellung fortzusetzen.

Der Parameter ignore_invalid_pages
Wenn der Wiederherstellungsprozess auf einem Replikat einen Link zu einer ungültigen Seite im WAL-Datensatz findet, geschiehtpanic-a. Durch Aktivieren wird der Parameter aktiviertignore_invalid_pages. Die Wiederherstellung wird mit einem möglichen Verlust an Integrität, Daten und anderen schwerwiegenden Folgen fortgesetzt. Der Parameter ist für Serverentwickler gedacht und sollte in den Fällen verwendet werden, in denen Sie noch versuchen müssen, die Wiederherstellung abzuschließen und das Replikat zu starten.

Ändern von primary_conninfo ohne Neustart
des Patches von Sergey Kornilov , mit dem Sie die Einstellungen ändern können primary_conninfo, primary_slot_nameund wal_receiver_create_temp_slotohne Neustart des Servers. Aus diesem Grund haben sie die Datei recovery.confin der 12. Version aufgegeben . Pg_basebackup-

Sicherungsmanifeste
erstellen jetzt ein „Manifest“ - eine JSON-Datei, die Informationen zur erstellten Sicherung enthält (Dateinamen und -größen, erforderliche WAL-Dateien sowie Prüfsummen für alles und jedes).
Das neue Dienstprogramm pg_validatebackup überprüft die Sicherungen auf Übereinstimmung mit dem Manifest und überprüft auch die Verfügbarkeit und Richtigkeit der für die Wiederherstellung erforderlichen WAL-Dateien mit dem Dienstprogramm pg_waldump (dies gilt nur für WAL-Dateien innerhalb der Sicherung selbst und nicht im Archiv).
Auf diese Weise können Sie Situationen erkennen, in denen die Sicherungsdateien beschädigt wurden oder verschwunden sind oder in denen eine Wiederherstellung aufgrund des Fehlens der erforderlichen Protokolldateien unmöglich wurde.

Einschränken des Replikationssteckplatzes für ungelesene Daten Der Replikationssteckplatz
ist ein praktischer, aber gefährlicher Mechanismus: Wenn der Client die Daten nicht rechtzeitig aus dem Steckplatz liest, können ungelesene WAL-Datensätze den gesamten Speicherplatz auf dem Server belegen. Verwenden Sie nun den Parametermax_slot_wal_keep_sizeSie können ein Limit für den maximalen Speicherplatz festlegen, der von ungelesenen Daten belegt werden kann. Wenn sich am nächsten Kontrollpunkt herausstellt, dass die Größe überschritten wird, wird der Steckplatz deaktiviert und der Platz freigegeben.

Windows


Unterstützung für Unix-Sockets unter Windows Unix-
Domain-Sockets werden unter Windows 10 unterstützt, obwohl sie standardmäßig deaktiviert sind.

Dokumentation


Die Dokumentation enthält zwei neue Anwendungen.
Nach einer langen Diskussion erschien Anhang M. Glossar . Das Glossar enthält derzeit 101 Begriffe.

Die Möglichkeit, die Farbe von Diagnosemeldungen von Konsolendienstprogrammen mithilfe einer Variablen hervorzuheben, PG_COLORwar früher. Dies ist jetzt in Anhang N dokumentiert . Farbunterstützung . Peter Eisentrouts ursprüngliche Absicht in diesem Patch war es, die kolorierte Ausgabe standardmäßig zu aktivieren. Und für diejenigen, die dies nicht wollten, wurde vorgeschlagen, die Variable explizit festzulegenNO_COLOR. Es gab jedoch mehr Gegner der Farbdifferenzierung von Nachrichten unter denen, die den Patch diskutierten. Daher beschlossen sie, nur die verfügbaren Möglichkeiten zu dokumentieren. Und wir haben einen neuen Abschnitt der ersten Ebene in der Dokumentation.



PG13, , PG14 . , . .

All Articles