Die Entwickler von OrioleDB haben den aktuellen Stand der low-level API, die für den Zugriff von Erweiterungen auf Tabellen und Indizes in PostgreSQL (Table/Index Access Method (AM) API) verwendet wird, analysiert und Verbesserungsvorschläge unterbreitet. Seit der Einführung dieser API in PostgreSQL 12 haben die Entwickler die Möglichkeit, alternative Datenspeichermechanismen zu erstellen. Trotz der Verfügbarkeit dieser API und den bekannten Einschränkungen des eingebauten Speichersystems gibt es jedoch bisher keine voll funktionsfähigen transaktionalen Speicher-Engines, die ausschließlich als Erweiterungen implementiert wurden.
Die am häufigsten nachgefragten Funktionen für alternative Tabellen-Engines in PostgreSQL sind:
- Alternative Implementierungen von MVCC, wie zum Beispiel Speicher, die auf einem UNDO-Protokoll basieren.
- Index-organisierte Tabellen, bei denen der Index keine optionale Ergänzung zur Tabelle ist, die Abfragen beschleunigt, sondern die Hauptdatenstruktur darstellt, in der die Tabellendaten gespeichert werden.
Die erforderlichen Änderungen an der API Table/Index AM zur Unterstützung alternativer Implementierungen von MVCC werden im Hinblick auf die OrioleDB-Erweiterung betrachtet, die entwickelt wurde, um bekannte Schwächen des eingebauten Speichermechanismus von PostgreSQL zu beheben. Das Problem ist, dass für die vollständige Integration von OrioleDB mit PostgreSQL Änderungen am PostgreSQL-Code erforderlich sind, was die Implementierung des Projekts erschwert und die Notwendigkeit der Modernisierung der aktuellen API Table AM unterstreicht.
Die API Table AM zwingt nicht direkt eine bestimmte Implementierungsweise von MVCC auf. Dennoch geht die API Table AM und die API Index AM von folgender Annahme aus: Jeder TID (Tuple/Row Identifier) wird entweder von allen Indizes indiziert oder gar nicht. Selbst wenn die Index AM mehrere Verweise auf einen TID hat (z. B. GIN), müssen all diese Verweise den gleichen indizierten Wert entsprechen.

Dieses Prinzip wurde kritisiert, weil es die Anzahl der Schreibvorgänge („Write Amplification“) erhöht – wenn ein indizierter Attribut aktualisiert wird, muss jeder Index in der Tabelle aktualisiert werden. Um die Vorteile des UNDO-Logs vollständig nutzen zu können oder eine andere Speichertechnik ohne „Schreibverstärkung“ (zum Beispiel die WARM-Methode) zu entwickeln, muss diese Annahme verletzt werden.

Die auf UNDO basierende Tabelle AM, die diese Annahme nicht verletzt, ähnelt der bestehenden HOT-Methode (Heap-Only Tuples), mit der Ausnahme, dass ältere Versionen von Zeilen im UNDO-Log gespeichert werden und nicht auf derselben Seite untergebracht werden müssen. Die Autoren sind jedoch der Meinung, dass dieser Vorteil nicht ausreicht, um die Existenz einer separaten Tabelle AM zu rechtfertigen.
Praktische Einschränkungen der bestehenden API:
- Beim Aktualisieren einer Tabellenzeile werden die Indizes nach dem Prinzip „Alles oder Nichts“ aktualisiert.
- Im API Index AM fehlt die Möglichkeit, bestimmte Tupel gezielt zu löschen. Derzeit können Tupel massenhaft mit den Methoden ambulkdelete und amvacuumcleanup aus Indizes entfernt werden. Ein Versuch, gezielte Löschungen über diese API durchzuführen, würde zu einer geringen Effizienz führen, da die meisten aktuellen Implementierungen den gesamten Index scannen müssen. Zudem erlaubt die API nicht anzugeben, welche der Tupel, die sich auf die gleiche TID beziehen, gelöscht werden sollen. Es kann nur alles entfernt werden.
- Indizes verweisen derzeit auf die Tabellenzeilen über die Blocknummer (32 Bit) und die Offsetnummer (16 Bit). Nur 11 Bit der Offsetnummer können sicher von der TID-Tabelle an alle Zugriffsmetoden des Index übergeben werden. In diesem Zusammenhang benötigen alternative MVCC-Implementierungen möglicherweise zusätzlichen Payload zusammen mit der TID. Zum Beispiel benötigt OrioleDB ein oder mehrere Bits, um 'delete-marking'-Indizes oder vollständige Sichtbarkeitsinformationen zu implementieren.
Zwei Ansätze wurden vorgeschlagen, um die Einschränkungen in der Praxis zu überwinden:
Ansatz 1: Die API Index AM bietet Möglichkeiten für alternative MVCC-Implementierungen.
Während Table AM weiterhin für alle Komponenten von MVCC verantwortlich ist, bietet Index AM die erforderlichen Funktionen für eine alternative Implementierung von MVCC, nämlich: die Speicherung der Benutzer-Nutzlast (payload) zusammen mit TID, eine Methode für das punktuelle Löschen und sogar eine Methode für das punktuelle Aktualisieren (wenn TID im Index nicht geändert werden kann, kann die Benutzer-Nutzlast das). Darüber hinaus müssen, da mehreren Tupeln im Index erlaubt ist, auf denselben TID zu verweisen, auch die API-Methoden, die beim Scannen des Index verwendet werden, aktualisiert werden.
Ansatz 2: Indizes, die MVCC unterstützen.
Eine Alternative wäre es, Indizes zuzulassen, die MVCC unterstützen. Das heißt, der "Executor" (oder möglicherweise Table AM) ruft einfach die Methoden insert() und delete() im Index AM auf, während Index AM die Möglichkeit bietet, unter Berücksichtigung von MVCC zu scannen. Dies würde das Scannen unter Verwendung von nur Indizes erheblich vereinfachen. Selbst der gesamte Table AM könnte in diesem Fall eine Zwischenschicht werden, die die Daten im Index speichert.
Das folgende Diagramm zeigt ein Beispiel. Der Wert des Index 2 wird durch Transaktion 11 von „A“ auf „B“ aktualisiert. Daher wird der Wert „A“ als xmax == 11 und der Wert „B“ als xmin == 11 gekennzeichnet. Auf diese Weise kann Index 2 gescannt werden, um nur sichtbare Tupel gemäß MVCC ohne Heap-Überprüfungen zu erhalten. Die Müllabfuhr für Index 2 kann ebenfalls ohne den Einsatz des Heaps durchgeführt werden.

Bei der Implementierung aller aufgeführten Neuerungen in die API der indexierten Zugriffsverfahren ist es unwahrscheinlich, dass es gelingt, alle Indizes gleichzeitig anzupassen, um alle neuen Funktionen zu unterstützen. Es ist realistischer, mehrere Implementierungen für eine Indexzugriffsmethode zuzulassen. Zum Beispiel wird das Erweiterungsmodul neben dem normalen B-Baum in der Lage sein, einen alternativen B-Baum mit Unterstützung für MVCC innerhalb des Index und für identifizierbare Datensätze beliebiger Länge zu implementieren.

Daher wird vorgeschlagen, nicht nur die API Table AM, sondern auch die API Index AM zu überarbeiten, die der PostgreSQL-Community über viele Jahre hinweg treu gedient hat. Darüber hinaus wird vorgeschlagen, den Index AM in eine logische Schicht und eine Implementierungsschicht zu unterteilen. Diese neu gestaltete Architektur wird es PostgreSQL ermöglichen, verschiedene Speicher-Modelle zu unterstützen.
Quelle: opennet.ru
