Am 15. September fand in Avito ein Treffen statt, bei dem wir ĂŒber die Skalierung von Anwendungen auf PostgreSQL sprachen. Heute möchte ich Materialien von ihm teilen - Videos, PrĂ€sentationen von Rednern, Fotos zeigen. AuĂerdem veröffentliche ich unter dem Schnitt eine Diskussion der Quizfragen , die wir hier auf HabrĂ© vor dem Mitap durchgefĂŒhrt haben. Und ich spreche ĂŒber meine EindrĂŒcke des Treffens.

Berichte
Verteilte Transaktionen und Zeitreisen. Stas Kelvich, Postgres Professional
Stas sprach ĂŒber verteilte Transaktionen und Zeitreisen.
PrÀsentation
Bewertungen:
Stas und sein Team haben hervorragende Arbeit geleistet! Ich hoffe, dass ihre Entscheidung von der Community genehmigt wird und wir diese Lösung in der neuen Version von Postgres sehen werden.
Skalieren einer Anwendung auf PostgreSQL in Avito: Tipps und Tricks. Konstantin Evteev, Avito
Ich hielt eine PrĂ€sentation ĂŒber die Skalierung einer Anwendung auf PostgreSQL in Avito und teilte unsere Tipps und Tricks mit.
PrÀsentation
Bewertungen:
Ein interessanter Ansatz: Kostantin erklĂ€rte sehr interessant und verstĂ€ndlich, auf welche Probleme Sie bei der Arbeit mit Daten in einer Microservice-Architektur stoĂen könnten, und schlug auch Lösungen fĂŒr die Skalierung von IP vor. Saga wird erinnert :)
Isolationsstufen fĂŒr logische Replikation und PostgreSQL-Transaktionen. Mikhail Tyurin
Michael hat einen Bericht ĂŒber die Isolationsstufen fĂŒr logische Replikation und PostgreSQL-Transaktionen erstellt.
PrÀsentation
Bewertungen:
Michael hob die subtilen Momente von Transaktionen hervor, die nicht nur fĂŒr AnfĂ€nger sofort sichtbar sind. Jeder muss darĂŒber Bescheid wissen.
OZO ist eine asynchrone typsichere PostgreSQL-Clientbibliothek nur fĂŒr Header fĂŒr C ++ 17. Sergey Handrikov, Yandex
Sergey erzĂ€hlte dem Publikum, wie OZO, die asynchrone typsichere PostgreSQL-Clientbibliothek fĂŒr C ++ 17, angeordnet ist, und lud ein, dazu beizutragen.
PrÀsentation
Bewertungen:
Meiner Meinung nach gelang es dem Autor, die Probleme in vorhandenen Bibliotheken und die Lösungen in den neuen C ++ - Bibliotheken in kurzer Zeit schnell aufzudecken. Daher bin ich froh, wenn diese Bibliotheken in OpenSource entwickelt werden, die grundlegenderen Dinge sind bereits implementiert, die sich nur freuen können.
Antworten auf die Quizfragen
Vor dem Treffen haben wir Sie eingeladen, Fragen zu Postgres zu beantworten. Heute möchte ich die richtigen Antworten zeigen. Sie sind unter den Spoilern (nur fĂŒr den Fall).
Es gibt eine leere Tabelle ohne BenutzerdatensĂ€tze ("UserId" int, "balance" int). Was wird als Ergebnis der Abfrage zurĂŒckgegeben?
with ins as ( insert into users select gs, gs * 10 from generate_series(1, 4) gs where gs%2 = 0) select * from users;
Was gibt die Anfrage zurĂŒck select * from users where UserId = 10;
beim Zugriff auf die Benutzertabelle nach Abschluss des vorherigen Jobs?
Die AntwortFEHLER: Spalte "Benutzer-ID" existiert nicht.
Definiert durch Enum CREATE TYPE Status AS ENUM ('wait', 'init', 'run', 'stop'); Welcher Befehl kann den Wert von 'init' entfernen?
Die AntwortEs gibt keine Standardmethode zum Entfernen eines Werts aus der AufzÀhlung.
Wie kann ich eine Liste der Funktionen in PostgreSQL erhalten?
Die AntwortWĂ€hlen Sie * From pg_proc;
Was wird als Ergebnis der Abfrage zurĂŒckgegeben?
select null = null, null is null, 1::smallint::boolean is true, null::bigint > 1
Die AntwortFEHLER: Typ smallint kann nicht in Booleschen Wert umgewandelt werden.
Der Junior-Entwickler Vasya wurde angewiesen, eine Abfrage zu schreiben, in der alle DatensÀtze aus der parent
Tabelle angezeigt werden, fĂŒr die die parent
Tabelle keine DatensÀtze enthÀlt.
Datenschema:
create table parent (parent_id serial primary key, payload text); create table child (child_id serial primary key, parent_id integer unique references parent (parent_id));
Vasya war sehr bemĂŒht und wollte sich nicht dem Dreck stellen. Deshalb stellte er acht verschiedene Fragen, um das Problem zu lösen:
-- 0 select p.parent_id, p.payload from parent p where not exists(select from child c where c.parent_id = p.parent_id); -- 1 select p.parent_id, p.payload from parent p where not (array[p.parent_id] && array(select c.parent_id from child c)); -- 2 select distinct p.parent_id, p.payload from parent p full join child c on (c.parent_id = p.parent_id) where c.parent_id is null; -- 3 select p.parent_id, p.payload from parent p where p.parent_id not in (select c.parent_id from child c); -- 4 select p.parent_id, p.payload from parent p left join child c on (c.parent_id = p.parent_id) where c.parent_id is null; -- 5 with w_child_with_parents as ( select c.parent_id, ( select count(*) from parent p where c.parent_id = p.parent_id) = 1 as parent_exists from child c) select p.parent_id, p.payload from parent p where p.parent_id in (select pc.parent_id from w_child_with_parents pc where not pc.parent_exists); -- 6 select p.parent_id, p.payload from parent p full join child c on (c.parent_id = p.parent_id) group by p.parent_id, p.payload having count(c) = 0; -- 7 select p.parent_id, p.payload from parent p where p.parent_id in ( select p2.parent_id from parent p2 except all select c2.parent_id from child c2);
Vasya stellte Ihnen seine Optionen vor, damit Sie ihm bei der Auswahl der besten helfen können. Er behauptet, dass alle Abfragen auf die gleiche Weise funktionieren: Tabellen werden im Speicher abgelegt und der Leistungsunterschied ist nicht signifikant (oder sogar unsichtbar). Als erfahrener Entwickler haben Sie jedoch festgestellt, dass möglicherweise nicht alle Anforderungen die Aufgabe lösen. Listen Sie die Abfragen auf, die die Aufgabe nicht lösen (und erklÀren Sie, warum).
Kurze AntwortDie Aufgaben 2, 3 und 5 lösen dieses Problem nicht (in einigen FÀllen auch Anforderung 1).
Die Antwort auf das Ergebnis des ExperimentsTestdaten:
Die "Unrichtigkeit" des Verhaltens zeigt sich, wenn die untergeordnete Tabelle DatensÀtze enthÀlt, deren parent_id null ist.
insert into parent (parent_id, payload) values (1, 'payload 1'), (2, 'payload 2'), (3, 'payload 3'), (4, 'payload 4'), (5, 'payload 5'); insert into child (child_id, parent_id) values (1, 1), (2, 3), (3, null), (5, 5);
Auf die angegebenen Testdaten
- Abfrage 1 funktioniert möglicherweise, je nachdem, ob die Intarray-Erweiterung installiert ist oder nicht.
- Abfrage 2 gibt eine zusĂ€tzliche Zeichenfolge zurĂŒck (null, null).
- Die Abfragen 3 und 5 geben eine leere Ergebnismenge zurĂŒck.
Interpretation der experimentellen Ergebnisse
Anforderung 1: Wenn die Intarray-Erweiterung in der Datenbank installiert ist ( https://www.postgresql.org/docs/current/static/intarray.html ), stĂŒrzt die Anforderung mit dem Fehler "FEHLER: Array darf keine Nullen enthalten" ab. Dieses Verhalten ist darauf zurĂŒckzufĂŒhren, dass die Erweiterung die Standardoperatoren ĂŒberschreibt und das Verhalten fĂŒr Arrays mit Nullelementen Ă€ndert.
In der Dokumentation heiĂt es:
Die Operatoren &&, @> und <@ entsprechen den gleichnamigen integrierten Operatoren von PostgreSQL, auĂer dass sie nur fĂŒr ganzzahlige Arrays funktionieren, die keine Nullen enthalten, wĂ€hrend die integrierten Operatoren fĂŒr jeden Array-Typ funktionieren. Diese EinschrĂ€nkung macht sie in vielen FĂ€llen schneller als die eingebauten Operatoren.
Anforderung 2: Aufgrund der vollstĂ€ndigen VerknĂŒpfung wird eine zusĂ€tzliche Zeichenfolge (null, null) angezeigt.
Anforderung 3: Gibt eine leere Ergebnismenge zurĂŒck, da die von der Unterabfrage gebildete Menge Nullelemente enthĂ€lt.
Dokumentation ( https://www.postgresql.org/docs/current/static/functions-subquery.html#FUNCTIONS-SUBQUERY-NOTIN ):
Beachten Sie, dass das Ergebnis des NOT IN-Konstrukts null und nicht true ist, wenn der linke Ausdruck null ergibt oder wenn es keine gleichen rechten Werte gibt und mindestens eine rechte Zeile null ergibt. Dies entspricht den normalen SQL-Regeln fĂŒr boolesche Kombinationen von Nullwerten.
Abfrage 5: Gibt eine leere Ergebnismenge zurĂŒck, da der Abschnitt w_child_with_parents aufgerufen wird, die Tabellen child und parent_id leer sind oder im Abschnitt ĂŒberhaupt nicht wiedergegeben werden.
Alle Fragen des Quiz wurden von drei Teilnehmern richtig beantwortet. Wir gaben dem Preis beim Treffen einen, zwei weitere Souvenirs gingen per Post.

Nachwort
Mehr als hundert Menschen kamen zu dem Treffen. Es war sehr schön, ein solches Publikum zu treffen. Laut einer Umfrage haben mehr als 60% der Mitap-GĂ€ste mehr als fĂŒnf Jahre Erfahrung in der Arbeit mit Datenbanken. Und es ist sehr schön, wenn die Berichte vom Publikum so lebhaft aufgenommen werden:

Am Rande der Meetings wurde viel darĂŒber gesprochen, dass PostgreSQL ein zunehmend verbreitetes Tool wird. Das ist tatsĂ€chlich so. Ich nutze diese Gelegenheit, um zu sagen, dass wir in Avito planen, das DBA-Team zu erweitern. Wenn Sie an ehrgeizigen Aufgaben fĂŒr ein groĂes Projekt interessiert sind, schauen Sie sich die Stelle bei My Circle an oder schreiben Sie mir.

AbschlieĂend möchte ich mich bei Kollegen von Yandex, Postgres Professional und natĂŒrlich Avito fĂŒr die wunderbaren Berichte bedanken, die wir gehört haben. Vielen Dank an die GĂ€ste, die an diesem Samstag zu uns gekommen sind und an die Live-Zuschauer. Und natĂŒrlich die # RuPostgres-Community fĂŒr Vertrauen.
Playlist mit allen Berichten hier .
Wir haben Fotoberichte auf Facebook und VKontakte veröffentlicht .

Bis bald!