NoSQL-Dokumentspeicher können ideal für die Verwaltung großer Mengen unstrukturierter Daten sein. Einige Unternehmen arbeiten jedoch mit unstrukturierten Daten, möchten aber dennoch die Funktionen herkömmlicher SQL-Datenbanken nutzen. So betreiben beispielsweise Medien- oder Nachrichtenagenturen Websites mit hohem Besucheraufkommen, die sich auf große Mengen an Text- und Bildinhalten konzentrieren. Obwohl sie diese unstrukturierten Daten speichern müssen, benötigen sie vielleicht nicht unbedingt die flexiblen Schemata oder die horizontale Skalierbarkeit, die NoSQL-Datenbanken bieten. Stattdessen benötigen sie die einfache Datenbankverwaltung und die Konsistenz, die eine relationale Datenbank wie PostgreSQL bietet.
Ist es möglich, das Beste aus beiden Welten zu bekommen? Ja.
Mit seinen Datentypen, die unstrukturierte Daten unterstützen sollen, bietet PostgreSQL einen goldenen Mittelweg, der es Ihnen ermöglicht, NoSQL-Funktionen innerhalb einer relationalen Datenbank zu nutzen, die kostengünstig und einfach zu verwalten ist. In diesem Artikel sehen wir uns an, wie Sie die Datentypen HStore und JSONB in PostgreSQL verwenden können, um mit unstrukturierten Daten zu arbeiten.
Bevor wir uns näher damit befassen, sollten wir uns kurz die Hauptunterschiede zwischen SQL- und NoSQL-Datenbanken ansehen.
Verstehen von SQL und NoSQL
SQL- und NoSQL-Datenbanken haben jeweils ihre eigenen Stärken und Schwächen. Um eine fundierte Entscheidung darüber zu treffen, welche Ihre Datenanforderungen am besten erfüllt, müssen Sie die Unterschiede genau kennen.
SQL (relationale) Datenbanken wie PostgreSQL und MySQL stellen Daten mit einer klaren und vorhersehbaren Struktur in Tabellen, Zeilen und Spalten dar. Sie halten sich an die ACID-Eigenschaften (Atomarität, Konsistenz, Isolation und Dauerhaftigkeit), die eine solide Grundlage für die Datenintegrität bilden, indem sie sicherstellen, dass Datenbanktransaktionen zuverlässig verarbeitet werden.
SQL-Datenbanken glänzen dort, wo Datenkonsistenz und -integrität von entscheidender Bedeutung sind, z. B. bei komplexen Abfragen und transaktionalen Systemen (wie bei Finanzanwendungen).
Im Gegensatz dazu eignen sich NoSQL-Datenbanken (Dokumentenspeicher) für große und vielfältige Datensätze, die sich nicht unbedingt für eine tabellarische Darstellung eignen. Beispiele für NoSQL-Datenbanken sind MongoDB, Cassandra und Couchbase. NoSQL-Datenbanken arbeiten mit flexiblen Schemata, sodass sich die Datenstrukturen im Laufe der Zeit weiterentwickeln können. Sie unterstützen auch die horizontale Skalierbarkeit, indem sie die Daten auf mehrere Server verteilen, um große Datenmengen und hohen Datenverkehr besser bewältigen zu können.
NoSQL-Datenbanken werden häufig in Anwendungen eingesetzt, bei denen Skalierbarkeit von entscheidender Bedeutung ist, z. B. bei der Verarbeitung großer Datenmengen in Echtzeitanwendungen oder großen Sprachmodellen (LLM). NoSQL-Datenbanken sind auch vorteilhaft, wenn es um vielfältige und sich entwickelnde Datenstrukturen geht, da sie es Organisationen ermöglichen, sich an die sich ändernden Datenanforderungen anzupassen.
Warum sollten Sie PostgreSQL als Dokumentenspeicher verwenden?
PostgreSQL ist eine relationale Datenbank, daher mag es unkonventionell erscheinen, sie als Option für NoSQL-Anforderungen zu betrachten. In Ihrer Situation kann es jedoch gute Gründe geben, PostgreSQL als Dokumentenspeicher zu verwenden.
Wenn Ihre Anforderungen an die Datenspeicherung vielfältig sind - Sie benötigen sowohl strukturierte, ACID-konforme Datenspeicherung als auch flexible, schemafreie Dokumentenspeicherung - dann können Sie PostgreSQL nutzen, um relationale und nicht-relationale Modelle zu kombinieren. Oder Sie wollen bestimmte NoSQL-Funktionen, aber auch die Datenkonsistenzgarantien, die mit ACID-Eigenschaften einhergehen. Als ausgereifte Technologie mit einer aktiven Community bietet PostgreSQL umfassende SQL-Unterstützung, erweiterte Indexierung und Volltextsuche. Diese Funktionen - in Kombination mit den NoSQL-Fähigkeiten - machen PostgreSQL zu einer vielseitigen Datenspeicherlösung.
Beschränkungen bei der Verwendung von PostgreSQL für NoSQL-ähnliche Daten
Trotz seiner Vielseitigkeit hat PostgreSQL im Vergleich zu traditionellen NoSQL-Datenbanken gewisse Einschränkungen. Während PostgreSQL vertikal skalieren kann, unterstützt es nicht von Haus aus die horizontale Skalierung oder verteilte Daten mit automatischem Sharding, Funktionen, die NoSQL-Datenbanken normalerweise bieten. PostgreSQL bietet auch keine Optimierungen für bestimmte NoSQL-Datenstrukturen wie z.B. spaltenreiche Speicher oder Graphdatenbanken. Schließlich bietet PostgreSQL keine abstimmbare Konsistenz zur Leistungsoptimierung, die Sie von einigen NoSQL-Datenbanken erhalten können.
Wenn Sie den Einsatz von PostgreSQL für große, unstrukturierte Datensätze in Erwägung ziehen, sollten Sie sich darüber im Klaren sein, dass diese Einschränkungen die Leistung und Skalierbarkeit beeinträchtigen können. Darüber hinaus führt die Vermischung von SQL- und NoSQL-Datenoperationen zu Komplexität. Eine sorgfältige Planung und das Verständnis für beide Paradigmen helfen Ihnen, mögliche Fallstricke zu vermeiden.
Mit dem richtigen Verständnis und dem richtigen Anwendungsfall kann PostgreSQL jedoch als leistungsfähiges Werkzeug dienen, das das Beste aus den beiden Welten SQL und NoSQL bietet.
HStore und JSONB in PostgreSQL
Bei der Betrachtung der Möglichkeiten, PostgreSQL als NoSQL-Lösung zu verwenden, stoßen wir auf drei Datentypen, die NoSQL-ähnliche Funktionalität bieten, aber jeder von ihnen hat einzigartige Eigenschaften und Anwendungsfälle.
- HStore: Dieser Datentyp ermöglicht es Ihnen, Schlüssel-Wert-Paare in einem einzigen PostgreSQL-Wert zu speichern. Er ist nützlich für die Speicherung halbstrukturierter Daten, die kein festes Schema haben.
- JSONB: Dies ist eine binäre Darstellung von JSON-ähnlichen Daten. Sie kann im Vergleich zu HStore komplexere Strukturen speichern und unterstützt alle JSON-Funktionen. JSONB ist indizierbar und damit eine gute Wahl für große Datenmengen.
- JSON: Dieser Datentyp ähnelt JSONB, obwohl er viele der Fähigkeiten und der Effizienz von JSONB vermissen lässt. Der JSON-Datentyp speichert eine exakte Kopie des Eingabetextes, die auch Leerzeichen und doppelte Schlüssel enthält.
Wir erwähnen den JSON-Datentyp als eine gute Wahl für die Speicherung von JSON-formatierten Daten, wenn Sie nicht die vollen Möglichkeiten von JSONB benötigen. Im weiteren Verlauf dieses Artikels werden wir uns jedoch in erster Linie auf HStore und JSONB konzentrieren.
HStore
Die PostgreSQL-Dokumentation beschreibt HStore als nützlich, wenn Sie "Zeilen mit vielen Attributen, die selten untersucht werden, oder halbstrukturierte Daten" haben. Bevor Sie mit dem HStore-Datentyp arbeiten können, müssen Sie die HStore-Erweiterung aktivieren:
> CREATE EXTENSION hstore;
HStore wird als null oder mehr durch Kommas getrennte Schlüssel => Wert dargestellt. Die Reihenfolge der Paare ist nicht von Bedeutung und wird bei der Ausgabe nicht zuverlässig beibehalten.
> SELECT 'foo => bar, prompt => "hello world", pi => 3.14'::hstore;
hstore
-----------------------------------------------------
"pi"=>"3.14", "foo"=>"bar", "prompt"=>"hello world"
(1 row)
Jeder HStore-Schlüssel ist eindeutig. Wenn eine HStore-Deklaration mit doppelten Schlüsseln erfolgt, wird nur eines der Duplikate gespeichert, und es gibt keine Garantie dafür, welches das sein wird.
> SELECT 'key => value1, key => value2'::hstore;
hstore
-----------------
"key"=>"value1"
(1 row)
Mit seiner flachen Schlüssel-Wert-Struktur bietet HStore Einfachheit und schnelle Abfragen, was es ideal für einfache Szenarien macht. Allerdings unterstützt HStore nur Textdaten und keine verschachtelten Daten, so dass es für komplexe Datenstrukturen nur bedingt geeignet ist.
Auf der anderen Seite kann JSONB eine größere Vielfalt an Datentypen verarbeiten.
JSONB
Der Datentyp JSONB akzeptiert JSON-formatierten Eingabetext und speichert ihn dann in einem dekomponierten Binärformat. Obwohl diese Konvertierung die Eingabe etwas verlangsamt, ist das Ergebnis eine schnelle Verarbeitung und effiziente Indexierung. JSONB behält keine Leerzeichen oder die Reihenfolge der Objektschlüssel bei.
> SELECT '{"foo": "bar", "pi": 3.14, "nested": { "prompt": "hello", "count": 5 } }'::jsonb;
jsonb
-----------------------------------------------------------------------
{"pi": 3.14, "foo": "bar", "nested": {"count": 5, "prompt": "hello"}}
(1 row)
Werden doppelte Objektschlüssel angegeben, wird der letzte Wert beibehalten.
> SELECT '{"key": "value1", "key": "value2"}'::jsonb;
jsonb
-------------------
{"key": "value2"}
(1 row)
Da JSONB komplexe Strukturen und vollständige JSON-Fähigkeiten unterstützt, ist es die ideale Wahl für komplexe oder verschachtelte Daten und ist HStore oder JSON vorzuziehen. Allerdings führt die Verwendung von JSONB im Vergleich zu HStore zu einem gewissen Leistungs-Overhead und einer erhöhten Speichernutzung.
Praktische Beispiele: Arbeiten mit HStore und JSONB
Betrachten wir einige praktische Beispiele, um zu zeigen, wie man mit diesen Datentypen arbeitet. Wir werden uns die Erstellung von Tabellen, grundlegende Abfragen und Operationen sowie die Indizierung ansehen.
Grundlegende HStore-Vorgänge
Wie bei jedem anderen Datentyp auch, können Sie Felder in Ihrer PostgreSQL-Datentabelle als HStore-Datentyp definieren.
> CREATE TABLE articles ( id serial primary key, title varchar(64), meta hstore );
Das Einfügen eines Datensatzes mit einem HStore-Attribut sieht folgendermaßen aus:
> INSERT INTO articles (title, meta)
VALUES (
'Data Types in PostgreSQL',
'format => blog, length => 1350, language => English, license => "Creative Commons"');
> SELECT * FROM articles;
id | title | meta ----+--------------------------+------------------------------------------ 1 | Data Types in PostgreSQL | "format"=>"blog", "length"=>"1350", "license"=>"Creative Commons", "language"=>"English"(1 row)
Mit HStore-Feldern können Sie bestimmte Schlüssel-Wert-Paare aus dem Feld abrufen, die durch von Ihnen bereitgestellte Schlüssel angegeben werden:
> SELECT title, meta -> 'license' AS license, meta -> 'format' AS format FROM articles;
title | license | format
---------------------------------+------------------+------------
Data Types in PostgreSQL | Creative Commons | blog
Advanced Querying in PostgreSQL | None | blog
Scaling PostgreSQL | MIT | blog
PostgreSQL Fundamentals | Creative Commons | whitepaper
(4 rows)
Sie können auch eine Abfrage mit Kriterien durchführen, die auf bestimmten Werten in einem HStore-Feld basieren.
> SELECT id, title FROM articles WHERE meta -> 'license' = 'Creative Commons';
id | title
----+--------------------------
1 | Data Types in PostgreSQL
4 | PostgreSQL Fundamentals
(2 rows)
Es kann vorkommen, dass Sie nur nach Zeilen suchen möchten, die einen bestimmten Schlüssel im Feld HStore enthalten. Zum Beispiel gibt die folgende Abfrage nur Zeilen zurück, in denen die Meta-HStore den Schlüssel note enthält. Dazu würden Sie den Operator ? verwenden.
> SELECT title, meta->'note' AS note FROM articles WHERE meta ? 'note';
title | note
---------------------------------+-----------------
PostgreSQL Fundamentals | hold for review
Advanced Querying in PostgreSQL | needs edit
(2 rows)
Eine Liste der nützlichen HStore-Operatoren und -Funktionen finden Sie hier. Sie können zum Beispiel die Schlüssel eines HStore in ein Array extrahieren oder einen HStore in eine JSON-Darstellung konvertieren.
> SELECT title, akeys(meta) FROM articles where id=1;
title | akeys
--------------------------+----------------------------------
Data Types in PostgreSQL | {format,length,license,language}
(1 row)
> SELECT title, hstore_to_json(meta) FROM articles where id=1;
title | hstore_to_json
--------------------------+------------------------------------------------
Data Types in PostgreSQL | {"format": "blog", "length": "1350", "license": "Creative Commons", "language": "English"}
(1 row)
Grundlegende JSONB-Vorgänge
Die Arbeit mit dem JSONB-Datentyp in PostgreSQL ist sehr einfach. Die Erstellung von Tabellen und das Einfügen von Datensätzen sieht folgendermaßen aus:
> CREATE TABLE authors (id serial primary key, name varchar(64), meta jsonb);
> INSERT INTO authors (name, meta) VALUES ('Adam Anderson', '{ "active":true, "expertise": ["databases", "data science"], "country": "UK" }');
Beachten Sie, dass das jsonb-Metafeld als Textstring im JSON-Format übergeben wird. PostgreSQL wird sich beschweren, wenn der von Ihnen angegebene Wert kein gültiges JSON ist.
> INSERT INTO authors (name, meta) VALUES ('Barbara Brandini', '{ "this is not valid JSON" }');
ERROR: invalid input syntax for type json
Anders als beim Typ HStore unterstützt JSONB verschachtelte Daten.
> INSERT INTO authors (name, meta) VALUES ('Barbara Brandini', '{ "active":true, "expertise": ["AI/ML"], "country": "CAN", "contact": { "email": "barbara@example.com", "phone": "111-222-3333" } }');
Ähnlich wie bei HStore können JSONB-Felder teilweise, d. h. nur mit bestimmten Schlüsseln, abgerufen werden. Zum Beispiel:
> SELECT name, meta -> 'country' AS country FROM authors;
name | country ------------------+--------- Adam Anderson | "UK" Barbara Brandini | "CAN" Charles Cooper | "UK"(3 rows)
Der Datentyp JSONB verfügt über viele Operatoren, die ähnlich wie HStore verwendet werden. Die folgende Verwendung des Operators ? ruft beispielsweise nur die Zeilen ab, in denen das Metafeld den Kontaktschlüssel enthält.
> SELECT name, meta -> 'active' AS active, meta -> 'contact' AS contact FROM authors WHERE meta ? 'contact';
name | active | contact
------------------+--------+-----------------------------------------------
Barbara Brandini | true | {"email": "barbara@example.com", "phone": "111-222-3333"}
Charles Cooper | false | {"email": "charles@example.com"}
(2 rows)
Arbeiten mit Indizes
Gemäß der Dokumentation bietet der Datentyp HStore "GiST- und GIN-Indexunterstützung für die Operatoren @>, ?, ?& und ?|". Eine ausführliche Erklärung der Unterschiede zwischen den beiden Indextypen finden Sie hier. Die Indizierung für JSONB verwendet GIN-Indizes, um die effiziente Suche nach Schlüsseln oder Schlüssel-Wert-Paaren zu erleichtern.
Die Anweisung zum Erstellen eines Indexes ist so, wie man es erwarten würde:
> CREATE INDEX idx_hstore ON articles USING GIN(meta);
> CREATE INDEX idx_jsonb ON authors USING GIN(meta);
SQL-Struktur mit NoSQL-Flexibilität
Kommen wir noch einmal auf den ursprünglichen Anwendungsfall zurück, den wir in der Einleitung erwähnt haben. Stellen Sie sich eine Nachrichtenagentur vor, die ihre Artikel in ähnlicher Weise speichert wie einen NoSQL-Dokumentenspeicher. Vielleicht kann der Artikel in JSON als ein geordnetes Array von Objekten dargestellt werden, die Abschnitte mit Textinhalten, Notationen und Formatierungen darstellen. Darüber hinaus ist jedem Artikel eine Vielzahl von Metadaten zugeordnet, und diese Metadatenattribute sind von einem Artikel zum nächsten inkonsistent.
Die obige Beschreibung fasst den größten Teil der NoSQL-Anforderungen des Unternehmens zusammen, aber alles andere, wie es seine Daten verwaltet und organisiert, ist eng mit einem relationalen Datenmodell verbunden.
Durch die Kombination der NoSQL-Fähigkeiten eines Datentyps wie JSONB mit den traditionellen SQL-Stärken von PostgreSQL kann das Unternehmen von flexiblen Schemata und schnellen Abfragen in verschachtelten Daten profitieren, während es gleichzeitig in der Lage ist, gemeinsame Operationen durchzuführen und Datenbeziehungen durchzusetzen. Die PostgreSQL-Datentypen HStore und JSONB bieten leistungsstarke Optionen für Entwickler, die die Struktur einer relationalen Datenbank benötigen, aber auch eine Datenspeicherung im NoSQL-Stil wünschen.
PostgreSQL im Maßstab
Möchten Sie die Speicherung und Abfrage von Daten im NoSQL-Stil unterstützen und dabei im Rahmen einer traditionellen relationalen Datenbank bleiben? Vielleicht arbeitet Ihre Organisation mit Dokumenten, ähnlich wie in diesem Beitrag beschrieben. Oder vielleicht suchen Sie nach Optionen für die Speicherung unstrukturierter Daten für ein großes Sprachmodell (LLM) oder ein anderes KI/ML-Vorhaben.
Der PostgreSQL Cluster im Linode Marketplace bietet Ihnen das relationale Modell und die Struktur einer SQL-Datenbank zusammen mit der horizontalen Skalierbarkeit einer NoSQL-Datenbank. Kombinieren Sie dies mit der Verwendung von HStore- oder JSONB-Datentypen, und Sie haben eine ideale Hybridlösung für die Nutzung von NoSQL-Funktionen bei der Arbeit mit PostgreSQL.
Kommentare