Einige Wochen vor dem wichtigen
Commit-Festival - dem letzten vor der
feature freeze
Version von
PostgreSQL 11 - sahen sich die
Hacker- Newsletter, die den Chipsatz im linken Paket komprimierten, den
MERGE- Thriller an. Der Thriller-Regisseur und CEO von
2ndQuadrant, Simon Riggs , versuchte mit beeindruckender Ausdauer und Einfallsreichtum, einen Patch zu veröffentlichen, der die Syntax des MERGE-Befehls in die Version implementiert. Riggs ist seit 2009 ein Comedian und mit dem Status eines Comedians können Sie Patches selbst genehmigen. Er wurde von nicht weniger angesehenen PostgreSQL-Komitees und Veteranen abgelehnt. Die Leidenschaften brodelten klar und implizit, es kam nicht einmal zu direkten Beleidigungen - eine überraschende Tatsache für Stammgäste in vielen Inlandsforen. Bis zur Klärung der Frage blieb jedoch eine gewisse Spannung bestehen, und es gibt nichts zu streiten.
Aber Leidenschaften sind Leidenschaften (sie werden weiter besprochen), und ich möchte die Essenz dieses völlig weit hergeholten Problems leidenschaftslos herausarbeiten.

Draußen verschmelzen
Wenn es vollständig vereinfacht ist, ist die Sache folgende: Wir haben 2 Tabellen mit denselben Feldern und unterschiedlichen Daten. Nehmen Sie Namen und Alter an. Wir müssen sie zu einem kombinieren. Es wäre jedoch notwendig zu entscheiden, was mit den Persönlichkeiten in beiden Tabellen geschehen soll. Höchstwahrscheinlich wollen wir alles in der Final Table und aktualisieren die Informationen auf übereinstimmende Personen. Es ist klar, dass dies auch in dieser Umgebung eine sehr häufige Aufgabe ist. Es kann ohne
MERGE
gelöst werden, eine komplexe Anfrage stellen, Sie können Trigger verwenden und so weiter. Aber es ist unpraktisch. Die nicht-kanonische Version von MERGE, die UPSERT (UPdate + inSERT) heißt, löst dieses Problem jedoch.
Der MERGE-Operator befindet sich im SQL-2003-Standard und ist in SQL-2008 bereits in seiner ganzen Pracht. Es ist in Oracle, DB2 und in MS SQL implementiert, was bedeutet, dass das Fehlen von MERGE diejenigen verärgert, die erwägen, von diesen DBMS auf PostgreSQL umzusteigen. Simon Riggs 'sehnsüchtiger Wunsch, so schnell wie möglich, bereits in PostgreSQL 11, wurde von den Wünschen der Kunden von 2ndQuadrant angetrieben und nicht von Ehrgeiz oder Streit.
Tatsächlich verfügt MERGE über umfangreiche Funktionen. Die Daten müssen nicht aus Tabellen entnommen werden, insbesondere nicht aus ähnlichen Strukturen.
Die Befehlssyntax lautet wie folgt:
MERGE INTO tablename USING table_reference ON (condition) WHEN MATCHED THEN UPDATE SET column1 = value1 [, column2 = value2 ...] WHEN NOT MATCHED THEN INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...]);
Sie können jedoch Folgendes tun:
MERGE [hint] INTO [schema .] {table | view} [table_alias] USING { subquery | [schema .] { table | view}} [table_alias] ON ( condition ) [ merge_update_clause ] [ merge_insert_clause ] [ error_logging_clause ] ;
Diese Syntax ist in Oracle implementiert. Mit anderen Worten, dann führt MERGE Aktionen aus, mit denen die Datensätze in der Zieltabelle target_table_name mithilfe von data_source in einem einzelnen SQL-Befehl geändert werden. Je nach den Bedingungen kann INSERT, UPDATE oder DELETE in Bezug auf die Datensätze in target_table_name ausgeführt werden. In diesem Fall kann target_table_name eine Ansicht sein, und data_source kann eine Reihe von
Tabellen oder Ansichten sein, die das Ergebnis einer Unterabfrage sind .
Zunächst führt die
MERGE
einen
left outer join
für die
data_source
mit dem
target_table_name
, wobei 0 oder mehr Kandidatenänderungsdatensätze vorgeschlagen werden.
WHEN
Klauseln werden in der angegebenen Reihenfolge berechnet. Sobald die Bedingung erfüllt ist, wird die entsprechende Aktion ausgeführt. Schlüsselwörter
WHEN [NOT] MATCH THEN
sind in
SQL
nicht sehr verbreitet, daher erinnern wir Sie daran, dass dies ein Steuerelementkonstrukt wie
if-else
in anderen Sprachen ist.
MERGE
target_table_name
DELETE
in Bezug auf
target_table_name
genauso wie
UPDATE, INSERT
oder
DELETE
, nur die Syntax des gesamten Befehls ist unterschiedlich.
Eine Klausel mit
ON
muss eine Verbindung zu allen Spalten des Primärschlüssels herstellen. Wenn andere Spalten angegeben werden, muss ein eindeutiger Index verwendet werden, damit die
[NOT] MATCHED
sofort die Aktionen für den Kandidatendatensatz bestimmen, um die Interaktion mit anderen Transaktionen auszuschließen.
MERGE
deterministischer Befehl: Sie können denselben Datensatz nicht mehrmals im selben MERGE-Befehl aktualisieren.
Ein Beispiel:
MERGE CustomerAccount CA USING RecentTransactions T ON T.CustomerId = CA.CustomerId WHEN MATCHED THEN UPDATE SET Balance = Balance + TransactionValue WHEN NOT MATCHED THEN INSERT (CustomerId, Balance) VALUES (T.CustomerId, T.TransactionValue);
oder mit einer Unterabfrage:
MERGE INTO bonuses D USING (SELECT employee_id, salary, department_id FROM employees WHERE department_id = 80) S ON (D.employee_id = S.employee_id) WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01 DELETE WHERE (S.salary > 8000) WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus) VALUES (S.employee_id, S.salary*.01) WHERE (S.salary <= 8000);
In
IBM DB2 funktioniert auch
die Syntax.
Wie sie sagen , "unter der Haube" wird dies ähnlich wie beim
UPDATE FROM
Konstrukt gemacht.
Seit 2008 hat
MS SQL auch MERGE
.
Aber selbst hinter einer einzigen Standardsyntax beginnt das Problem der Auswahl aus einer beträchtlichen Anzahl von Mechanismen und Implementierungsmethoden. Das Team sollte auf verschiedenen Ebenen der Transaktionsisolation mit unterschiedlichen Sperralgorithmen arbeiten und sich auf wettbewerbsintensive oder weniger wettbewerbsfähige Betriebsarten konzentrieren. Und um diese komplizierte Logik zu implementieren, müssen Sie, wie Sie vielleicht vermuten, viele DBMS-Komponenten berühren.
UPSERT, Pseudo-MERGE
Es ist klar, dass DBMS-Entwickler nach Kompromisslösungen suchten und sich weigerten, die Standardsyntax buchstäblich zu reproduzieren. Das Plus dieses Ansatzes ist die Freiheit. Sie können organische Mechanismen verwenden, die für ein bestimmtes DBMS organisch sind. Sie können die Implementierung für Aufgaben optimieren, die Sie für Ihre Benutzer als am relevantesten erachten.
In
MySQL gibt es beispielsweise einen
REPLACE
Befehl, der wie
INSERT
funktioniert. Wenn jedoch die neuen und alten Zeilen im
PRIMARY KEY
oder
UNIQUE
Index dieselben Werte haben, wird die alte Zeile vor dem Einfügen der neuen Zeile gelöscht. Es gibt aber auch
INSERT ... ON DUPLICATE KEY UPDATE
wo
INSERT
und
UPDATE
auftreten (anstelle von
DELETE
in
REPLACE
). Das ist
UPSERT
. Und
es gibt INSERT IGNORE
, das das Einfügen einfach nicht durchführt, ohne unter bestimmten Einschränkungen einen Fehler (aber eine Warnung) in der
INSERT IGNORE
.
Chroniken von PG MERGE
In der PostgreSQL-Community begann das Gespräch über MERGE im Jahr 2005, als Jaime Casanova fragte,
ob jemand in der Community mit der Entwicklung von MERGE
.
Peter Eisentraut schlug vor, zu diskutieren, ob es sich lohnen würde, eine MERGE-Option für PostgreSQL zu entwickeln: eine ähnliche Implementierung in MySQL, oder es wäre besser, Ihre Bemühungen auf eine Oracle-Version des MERGE
Typs zu lenken, die eine MERGE
Funktionalität aufweist. Lohnt es sich jedoch, Anstrengungen in diese Richtung zu unternehmen?Inmitten einer kurzen Diskussion erscheint der Protagonist dieser Erzählung
Simon Riggs mit den Worten:
MERGE ist sowohl für OLTP-Systeme als auch für DW (Data Warehouse - Data Warehouses, dh analytische Anwendungen, bei denen komplexe Abfragen, aber nicht zu wettbewerbsfähige Umgebungen und Daten selten aktualisiert werden und wenn sie aktualisiert werden, normalerweise in großen Blöcken, nützlich. <...> Wir können MERGE als eine Variante von COPY FROM implementieren, es wird sehr cool sein.Alle sind sich einig: Ja, cool. Genauer gesagt, fast alles:
Stephen Frost :
Ich glaube, ich bin nicht der einzige, der sagt, dass ich einen vollwertigen, konformen MERGE-Standard brauche.Bruce Momjian hat einen anderen, pragmatischeren Vorschlag:
Es scheint mir, dass wir einige Optionen, die wir implementieren können, in MERGE
implementieren müssen, und im Rest werden wir einen Fehler geben (und in Fällen, in denen es notwendig sein wird, die gesamte Tabelle zu blockieren). Und nachdem wir Feedback von Benutzern erhalten haben, werden wir überlegen, was als nächstes zu tun ist.Aber bisher passiert nichts.
Das Eis ist gebrochen
Im Jahr
2008 forderte Simon Riggs erneut auf, sich mit MERGE zu befassen - welche der Möglichkeiten zu wählen (zu diesem Zeitpunkt erschien bereits eine neue Version von MERGE im SQL-2008-Standard, soweit es sich um einen Entwurf handelte). Er malt ausführlich die aktuelle Implementierung von Oracle, IBM und MS SQL sowie die alternative Syntax von MySQL und Teradata. Und wenig später erwähnt er bereits den
Beginn der Arbeit im 2. Quadranten in dieser Richtung.
Peter Eisentraut
schreibt in seinem Blog :
Natürlich ist Riggs einer der qualifiziertesten Spezialisten, er kann die Arbeit an der Implementierung von MERGE leiten.Aber hier kommt die erste unerwartete Wendung: Ein
Student ist in das Problem involviert - ein Teilnehmer an der Entwicklung des
GSoC- Programms,
dh Google Summer of Code. Sein Name ist
Boxuan Bxzhai - ich
nehme nicht an, den Nachnamen zu transkribieren. Bald schreibt er, dass die Arbeit fast erledigt ist.
Aber fast zählt nicht.
Greg Smith von 2ndQuadrant (d. H. Simon Riggs Verbündeter) schreibt:
Wir haben also einen Patch im Code, der ein halbes Dutzend schwerwiegender ungelöster Probleme enthält. Ich schweige über die Kleinen. Die Probleme sind zu tief, um den Code für das Commitfest fertigzustellen. Inzwischen ist seit langem nichts mehr von Boxuan zu hören. Wir könnten ihm helfen, aber wo ist er? Wer weiß Bescheid?Eine Diskussion über Implementierungspfade wird
2014 wieder aufgeflammt, aber es passiert wieder nichts: Es gibt keinen Code.
Schließlich schreibt
Simon Riggs bereits
2017 :
Ich arbeite an Code, um MERGE
für PostgreSQL Version 11 zu übernehmen . Wir verwenden dieselben Mechanismen, die dem bereits funktionierenden INSERT ON CONFLICT
zugrunde INSERT ON CONFLICT
, sodass keine Änderungen an der Infrastruktur erforderlich sind. Grundsätzlich wird nur die Syntax zusätzlich zu den verfügbaren implementiert. Aber ich schreibe meinen Code von Grund auf neu, ich verwende keine früheren Entwicklungen.Wir sprechen über Peter Geoghegan (
VMware ), der zu diesem Zeitpunkt bereits in 9.5 alternativer
INSERT .. ON CONFLICT UPDATE
Syntax
INSERT .. ON CONFLICT UPDATE
, anders als der SQL-Standard, aber immer noch mit
MERGE
und
REPLACE
in MySQL verbunden.
Zuerst wurde Simons Arbeit mit Ausrufen von Nizza Arbeit getroffen! Obwohl
Robert Haas unterstützend ist, warnt er vor möglichen Serialisierungsanomalien.
INSERT .. ON CONFLICT UPDATE
mit
INSERT .. ON CONFLICT UPDATE
umzugehen
INSERT .. ON CONFLICT UPDATE
, ohne MERGE an der Basis, ist es irgendwie ruhiger.
PostgreSQL
UPSERT
Autor
UPSERT
selbst:
Ich würde den MERGE
ON CONFLICT DO UPDATE
und MERGE
nicht mischen. <...> Zum Laden großer Datenmengen ( bulk load
) würde ich beispielsweise den merge join
Algorithmus verwenden. <...> Im Allgemeinen MERGE
die Vorteile von MERGE
damit zusammen, dass normale Verbindungen dort auf die übliche Weise funktionieren: nested loop, hash, merge
. Und in INSERT … ON CONFLICT
gibt es überhaupt keine Joins.Haas:
Wie Peter denke ich, dass auf diese Weise eine so starke Sperre bei der Ausführung einer DML
Anfrage DML
aussieht. Es ist unwahrscheinlich, dass sich jemand darüber freut, dass nur eine Person gleichzeitig mit MERGE
arbeiten kann.Für Neugierige: Geigan zerlegt
hier und
hier die Feinheiten und
UPSERT
Unterschiede zwischen
MERGE
und
MERGE
(wir speichern die
archivierte Korrespondenz von PostgreSQL auf unserer Website).
Simon widersetzt sich. Er appelliert an die jüngste Geschichte. Zum Thema Abschnitt sagten sie auch "eine neue Syntax, nichts weiter". Aber es stellte sich als sehr nützliche Sache heraus.
Aber ich habe nicht vor, sofort alles zu realisieren, was in MERGE ist. Wir werden das Gleiche tun wie bei der Partitionierung - wir teilen die Entwicklung in Phasen ein.Und noch ein Argument ist meiner Meinung nach sehr überzeugend:
Gut. Aber lass uns wählen. Ich schlage eine praktische Option vor. 10 Jahre werden bald vom ersten ernsthaften Versuch kommen, MERGE
zu entwickeln. Ist es nicht an der Zeit, etwas zu tun, um eine nützliche Lösung zu finden, anstatt auf weitere 10 Jahre der perfekten Lösung zu warten? Vorausgesetzt, es existiert überhaupt.Schließlich kommt der Patch in der Community an. Welches Datum? Stellen Sie sich bitte vor. Nein, sie haben es nicht erraten: Simon schickt ihn am 30. Dezember 2017. Und legt fest, dass dies ein WIP-Patch ist, dh Work in Progress - ein Patch in Arbeit.
Simon, Januar:
Der Patch wird ohne spezielle Fehler abgeschlossen. 1200 Codezeilen plus Tests und Dokumentation. Ich werde ihn für dieses Commitfest verpflichten, und wir werden die RLS- (Row Level Security - Schutz auf Aufzeichnungsebene) und Partitionierungsunterstützung später abschließen.Kaste der Ausschüsse
Hier müssen wir einen Schritt beiseite treten und die Rolle des Kommissars in der Gemeinde erklären. Die Funktionen des Beauftragten, dh desjenigen, der befugt ist, den Patch in der nächsten Version zu akzeptieren, haben sich historisch geändert. Es war einmal, als es nur wenige Entwickler gab, das Recht, sich zu verpflichten, wurde großzügig verteilt. Zum Beispiel erhielt der berühmte (auf einem ganz anderen Gebiet)
Julian Assange den Titel eines Kommandanten, der nur sechs Patches verfasste. Jetzt ist es nicht einfach, Kommissar zu werden. Auf der Liste von ein paar Dutzend Personen stehen keine Emporkömmlinge. Boyus Momdjan (
EnterpriseDB ) hat 13.363 Commits, Tom Lane (Tom Lane,
Crunchy Data ) 13127, Robert Haas (
EnterpriseDB ) - 2074. Der
einzige Committer aus Russland ist
übrigens Fedor Sigaev (Teodor Sigaev,
Postgres Professional ) mit seinen 383 Commits . Simon Riggs selbst hat 449 von ihnen. Ich wiederhole: Er hat als Kommissar genug Autorität, um Patches zu nehmen und zu begehen - seine und seine Mitarbeiter. Eine andere Sache ist, dass es sich kaum lohnt, dies zu tun, indem man offen die Meinungen anderer führender Leuchtenkomitees vernachlässigt. Sie können auch den Status eines Kommissars entziehen, aber zumindest werden sie
revert
Patch zurücksetzen.
Bruch im Kampf
Natürlich finden sie in dem "hoffnungslosen" Patch, der im Allgemeinen hastig erstellt wurde, neue Fehler. Neue Versionen rollen als Antwort.
Ende Januar erscheint ein neuer Charakter: der Entwickler von 2ndQuadrant
Pavan (sein Name ist jeder mit Namen; vollständig Pavan Deolasee). Jetzt hat es die Community mit einem Tandem zu tun: Pavan sendet neue Versionen und bedankt sich für die Kritik, und Simon bricht sie mit einem bemerkenswerten Marketingdruck.
Haas:
Ich denke nicht, dass es sich lohnt, einseitige Entscheidungen über den Ausschluss von Funktionen zu treffen, die überall funktionieren. Wenn wir uns einig sind, dass einige Funktionen nicht in diesem Patch enthalten sind, ist dies eine Sache. Und es ist völlig anders, dass in den Kommentaren zu diesem Anlass alle ihre Uneinigkeit zum Ausdruck brachten. Und wir haben tatsächlich nicht gehört, warum diese Funktionen ausgeschlossen werden sollten.Die Logik wurde wie folgt dargestellt:
- a priori gibt es ernsthafte Probleme, weil sie nur in den Entwicklungen im Stil des "Kavallerieangriffs" liegen können.
- Die Unterstützung selbst wichtiger Funktionen wie der neuen Partitionierung in den Versionen 10-11, CTE (Common Table Expressions = WITH-Abfragen) oder RLS (Row Level Security) kann auch dann abgeschlossen werden, wenn der Patch in der aktuellen Version akzeptiert wurde, jedoch nur, wenn die vorgeschlagene Architektur für den Aufbau auf der Oberseite geeignet ist ihre gewünschte Funktionalität.
Der zweite Peter Geigan formuliert dies:
Normalerweise achte ich auf die Unterstützung verschiedener Funktionen, da dies die allgemeine Überzeugung stärkt, dass das Design so gestaltet ist, wie es sollte . Und wenn solche Probleme durch die Unterstützung von WITH
Ausdrücken [ CTE
] verursacht werden, komme ich auf die Idee, dass die zugrunde liegende Architektur so ist, dass sie hier und da Probleme verursacht.In der Zwischenzeit nähert sich die Stunde X (das letzte Komiteefest) und die Wolken über MERGE ziehen auf. Es ist nicht so, dass die Gründerväter speziell ernsthafte Probleme in der Architektur der Patches von Simon und dann Pavan suchten. Ich musste nicht nach Problemen suchen, sie öffneten sich bereitwillig.
Die Auflösung nähert sich
Die Handlung beschleunigt sich. Trotz der coolen Haltung anderer Komitees zu seinem Unternehmen beschließt Simon
am 2. April , den
Befehl nach dem SQL: 2016- Patch zu übernehmen, fügt die Dateien hinzu, Depesz (Hubert Lubachevsky) schafft es
, ihn auf seinem Blog
anzukündigen , aber am selben Tag rollt Simon alles zurück, weil Fehler.
Legen Sie am nächsten Tag erneut fest, indem Sie
WITH
Unterstützung hinzufügen.
Als Reaktion darauf sind die Vorwürfe wirklich schwerwiegend.
Andres Freund (
EnterpriseDB ) schreibt:
Die Architektur für MERGE im Parser und im Executor hat mich nicht zuverlässig beeindruckt. Das Erstellen versteckter Verknüpfungen während der Parsing-Analyse ist eine wirklich schlechte Idee. Diese Struktur des Executors muss komplett geändert werden.Tom Lane:
Das Design des Analysebaums ist schwach.Sie überladen die InsertStmt
Funktion, fährt er fort, sie führt INSERT
überhaupt nicht aus, hat aber zufällig die gleichen Felder wie das ursprüngliche. Und nicht alle, aber einige. Das ist schlecht, es führt zu Verwirrung.Fügen wir Beobachtungen von
Fedor Sigayev hinzu :
Im Parser wurden MERGE
bezogene INSERT
Knoten MERGE
, die mit einer Reihe zusätzlicher Felder aufgehängt waren. Wenn Sie sich den Ausführungsplan in ANALIZE
, werden Sie nicht sofort verstehen, ob es sich um ein reguläres INSERT
oder um MERGE
: MERGE
zu verstehen, müssen Sie sich zusätzliche Felder ansehen.Simon, ruhig:
OK, wir werden das ändern und morgen eine neue Datei senden .
Haas:
Ich stimme Peter zu. Die Wahl der Architektur ist erfolglos.Simon gibt nicht auf.
Als Reaktion auf die Kritik an Tom Lane begeht der
6. April einen neuen Patch in der im Parser geänderten Fassung.
Verhandlung und Kapitulation
Bruce Momjan
6. April :
Ich möchte darauf hinweisen, dass die Leute Sie nicht gebeten haben, hart zu arbeiten, um dringend etwas zu reparieren. Sie haben dich gebeten, den Patch zurückzuziehen. Sie können natürlich hart arbeiten und hoffen, dass sie ihre Meinung ändern, aber auch hier haben sie Sie nicht danach gefragt.Simon:
Wenn Tom [Lane] und Andres [Freund] in den verbleibenden Tagen immer noch das Gefühl haben, dass ihre Befürchtungen nicht zerstreut wurden, werde ich den Patch gerne ohne weiteres zurücksetzen.Tom Lane:
Ich stimme immer noch dafür, dass der Patch zurückgesetzt wird. Selbst wenn er jetzt perfekt wäre, haben die Menschen jetzt keine Zeit, sich davon zu überzeugen - bis hin zu anderen dringenden Angelegenheiten.Das ist alles.
Simon sagte OK und der Kampf bei
MERGE
vorbei. Alle Patches wurden zurückgepumpt, das Thema wurde auf das nächste Commitfest mit dem Status "Warten auf den Abschluss des Autors" verschoben. Die Teilnehmer der Show schlossen Frieden.

Nach der Korrespondenz der letzten Wochen scheint jedoch eine gewisse Spannung bestehen zu bleiben.
Versprochene Moral
- Glücklicherweise verfügt die PostgreSQL-Community über natürliche und formale Mechanismen für das (fast) konfliktfreie Screening von Versuchen unreifer Lösungen. Auch wenn sie von angesehenen Entwicklern im Rang eines Unternehmensleiters geschlagen werden, dessen Beitrag zur Entwicklung von PostgreSQL enorm ist. Und Kunden, denen es an Funktionalität mangelt, drängen auf Investitionen.
- Leider bleibt die Community oft stehen. Es ist träge bei der Annahme selbst eindeutig relevanter Entwicklungen. Manchmal ist irrationaler Perfektionismus enthalten. Die Erfahrung von Postgres Professional, wo ich arbeite, bestätigt dies. Wir haben 3 Jahre lang einen großen und wichtigen Patch mit INCLUDE-Indizes erstellt . Eine nützliche Reihe von Patches für die Arbeit mit JSON / JSONB wartet noch. Der Ausdruck "Gib der Gemeinde deine Entwicklung" bedeutet nicht wirklich Geben, sondern Schlagen : Der Gast wird mit offenen Armen begrüßt und in die Quarantäne geführt.
PS:
Haftungsausschluss des Autors : Wir wollten nur ein Stück Gemeinschaftsleben zeigen. Alle Namensübereinstimmungen sind zufällig :)
PPS: Samurai
Natalia Levshina .