Erklärung von JSONB, eingeführt von PostgreSQL

345

PostgreSQL hat gerade JSONB eingeführt und es ist bereits ein Trend bei Hacker-News . Es wäre großartig, wenn jemand erklären könnte, wie es sich von Hstore und JSON unterscheidet, die zuvor in PostgreSQL vorhanden waren. Was sind seine Vor- und Nachteile und wann sollte jemand darüber nachdenken, es zu verwenden?

Peeyush
quelle
4
Von PGCon2014: youtube.com/…
msanford
5
Die @ CraigRinger-URL ist nicht präzise genug, jetzt, 1 Jahr später, zeigt sie nicht einmal nah genug an JSONB-bezogenen Inhalten.
Berkus
2
@berkus Ich dachte, ich hätte auf den spezifischen Beitrag verlinkt. Wie frustrierend.
Craig Ringer
1
Es zeigt auf das spezifische Video.
Talonx

Antworten:

455

Erstens hstorehandelt es sich um ein Contrib-Modul, mit dem Sie nur Schlüssel => Wertepaare speichern können, wobei Schlüssel und Werte nur texts sein können (Werte können jedoch auch SQLs NULLsein).

Mit Both json& jsonbkönnen Sie einen gültigen JSON- Wert (in der Spezifikation definiert ) speichern .

F.ex. diese sind gültig JSON Darstellungen: null, true, [1,false,"string",{"foo":"bar"}], {"foo":"bar","baz":[null]}- hstoreist nur ein kleiner Teilmenge im Vergleich zu dem, was JSON ist in der Lage (aber wenn Sie benötigen nur diese Teilmenge, es ist in Ordnung).

Der einzige Unterschied zwischen json& jsonbist ihre Speicherung:

  • json wird im Klartextformat gespeichert, während
  • jsonb wird in einer binären Darstellung gespeichert

Dies hat drei Hauptfolgen:

  • jsonbZum Speichern wird normalerweise mehr Speicherplatz benötigt als json(manchmal nicht)
  • jsonb Das Erstellen der Eingabedarstellung dauert länger als json
  • jsonOperationen benötigen erheblich mehr Zeit als jsonb(& Parsing muss auch jedes Mal durchgeführt werden, wenn Sie eine Operation mit einem jsoneingegebenen Wert ausführen )

Wann jsonbmit einer stabilen Version verfügbar sein wird, gibt es zwei Hauptanwendungsfälle, bei denen Sie leicht zwischen ihnen wählen können:

  1. Wenn Sie in Ihrer Anwendung nur mit der JSON-Darstellung arbeiten, wird PostgreSQL nur zum Speichern und Abrufen dieser Darstellung verwendet json.
  2. Wenn Sie viele Operationen mit dem JSON-Wert in PostgreSQL ausführen oder die Indizierung für ein JSON-Feld verwenden, sollten Sie diese verwenden jsonb.
pozs
quelle
1
Hallo, da es eine binäre Darstellung hat, warum wird jsonbdies nicht unterstützt? UPDATE test SET data->'a' = 123 WHERE id = 1;vonCREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
Kokizzu
1
Kokizzu, es ist in 9.5 möglich. wiki.postgresql.org/wiki/…
ChelowekKot
1
Nur hinzufügen, einer der Gründe , weshalb Sie auch verwenden könnten jsonüber jsonb, wenn für Legacy - Gründe Code raubend Ihre jsonabhängig ist von der Reihenfolge der jsonFelder und sie können nicht neu angeordnet werden.
djdrzzy
4
Aus den alten Gründen: In JSON gibt es keinen semantischen Unterschied, wenn die Schlüssel-Wert-Paare eines Objekts (Tabelle, Karte, Hash, wie auch immer es in der Host-Sprache aufgerufen wird) unterschiedlich geordnet sind. Wenn Sie sich darauf verlassen, verwenden Sie tatsächlich etwas anderes als JSON. - Für textvs json.: Letzteres wird mit JSON-Validierung geliefert. Bei ungültigem JSON schlägt dies also nur beim Einfügen fehl, anstatt jedes Mal, wenn Ihre Anwendung es liest (weil es eine ungültige Darstellung erhält). Sie können letzteres auch sicher jsonbin die Datenbank umwandeln.
pozs
2
Dies ist ein großartiger Beitrag zur Erläuterung der Implementierungsdetails für JSONB ( pgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html )
manugupt1
131

Peeyush:

Die kurze Antwort lautet:

  • Wenn Sie in PostgreSQL viele JSON-Manipulationen durchführen , z. B. Sortieren, Schneiden, Spleißen usw., sollten Sie JSONB aus Geschwindigkeitsgründen verwenden.
  • Wenn Sie indizierte Suchvorgänge für die Suche nach beliebigen Schlüsseln in JSON benötigen, sollten Sie JSONB verwenden.
  • Wenn Sie keines der oben genannten Verfahren ausführen, sollten Sie wahrscheinlich JSON verwenden.
  • Wenn Sie die Schlüsselreihenfolge, Leerzeichen und doppelte Schlüssel beibehalten müssen, sollten Sie JSON verwenden.

Für eine längere Antwort müssen Sie warten, bis ich eine vollständige "HowTo" -Beschreibung näher an der Version 9.4 gemacht habe.

FuzzyChef
quelle
74

Eine einfache Erklärung des Unterschieds zwischen json und jsonb ( Originalbild von PostgresProfessional ):

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;

          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  • json: Textspeicherung «wie sie ist»
  • jsonb: keine Leerzeichen
  • jsonb: keine doppelten Schlüssel, letzter Schlüssel gewinnt
  • jsonb: schlüssel werden sortiert

Mehr in Rede Video und Diashow - Präsentation von jsonb Entwicklern. Auch sie eingeführt JsQuery stellt pg.extension leistungsstarke jsonb Abfragesprache

ChelowekKot
quelle
1
Danke, ich habe es in Text ersetzt
ChelowekKot
55
  • hstore ist eher ein "breitspaltiger" Speichertyp, es ist ein flaches (nicht verschachteltes) Wörterbuch von Schlüssel-Wert-Paaren, das immer in einem einigermaßen effizienten Binärformat (eine Hash-Tabelle, daher der Name) gespeichert ist.
  • jsonspeichert JSON-Dokumente als Text, führt eine Validierung durch, wenn die Dokumente gespeichert sind, und analysiert sie bei Bedarf bei der Ausgabe (dh Zugriff auf einzelne Felder); Es sollte die gesamte JSON-Spezifikation unterstützen. Da der gesamte JSON-Text gespeichert ist, bleibt seine Formatierung erhalten.
  • jsonbAus Leistungsgründen werden Verknüpfungen verwendet: JSON-Daten werden bei der Eingabe analysiert und im Binärformat gespeichert, Schlüsselreihenfolgen in Wörterbüchern werden nicht beibehalten und doppelte Schlüssel werden nicht verwendet. Der Zugriff auf einzelne Elemente im JSONB-Feld ist schnell, da der JSON-Text nicht ständig analysiert werden muss. Bei der Ausgabe werden JSON-Daten rekonstruiert und die anfängliche Formatierung geht verloren.

IMO, gibt es keinen wesentlichen Grund für die nicht verwenden , jsonbsobald es verfügbar ist, wenn Sie mit maschinenlesbaren Daten arbeiten.

Ivan Voras
quelle
24

JSONB ist eine "bessere" Version von JSON.

Schauen wir uns ein Beispiel an:

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;
          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  1. JSON speichert Leerzeichen. Deshalb können Leerzeichen angezeigt werden, wenn der Schlüssel "a" gespeichert ist, während JSONB dies nicht tut.
  2. JSON speichert alle Schlüsselwerte. Dies ist der Grund, warum Sie mehrere Werte (2 und 1) für den Schlüssel "a" sehen können, während JSONB nur den letzten Wert "speichert".
  3. JSON behält die Reihenfolge bei, in der Elemente eingefügt werden, während JSONB die "sortierte" Reihenfolge beibehält.
  4. JSONB-Objekte werden in JSON als dekomprimierte Binärdatei gespeichert, im Gegensatz zu "Rohdaten", bei denen beim Abrufen keine erneute Analyse der Daten erforderlich ist.
  5. JSONB unterstützt auch die Indizierung, was ein erheblicher Vorteil sein kann.

Im Allgemeinen sollte man JSONB bevorzugen, es sei denn, es gibt spezielle Anforderungen, wie z. B. ältere Annahmen zur Reihenfolge der Objektschlüssel.

Subodhkarwa
quelle
13

Ich war heute auf der pgopen. Benchmarks sind viel schneller als Mongodb. Ich glaube, sie waren für ausgewählte Personen um 500% schneller. Im Gegensatz zu Mongodb war so ziemlich alles mindestens um 200% schneller als eine Ausnahme. Derzeit ist ein Update ein Update, bei dem die gesamte JSON-Spalte komplett neu geschrieben werden muss, was Mongodb besser handhabt.

Die Gin-Indizierung auf jsonb klingt erstaunlich.

Auch Postgres werden intern Arten von Jsonb beibehalten und dies grundsätzlich mit Typen wie numerisch, Text, Booleschen Werten usw. abgleichen.

Joins sind auch mit jsonb möglich

Wenn Sie PLv8 für gespeicherte Prozeduren hinzufügen, wird dies für die Entwickler von node.js im Grunde ein wahr gewordener Traum.

Da es als binäres jsonb gespeichert ist, werden auch alle Leerzeichen entfernt, die Reihenfolge der Eigenschaften geändert und doppelte Eigenschaften mit dem letzten Vorkommen der Eigenschaft entfernt.

Abgesehen davon, dass der Index bei der Abfrage einer jsonb-Spalte im Gegensatz zu einer json-Spalte postgres nicht die Funktionalität ausführen muss, um den Text in jeder Zeile in json zu konvertieren, was wahrscheinlich allein viel Zeit spart.

John
quelle
7

In Bezug auf die Unterschiede zwischen jsonund jsonbDatentypen ist die offizielle Erklärung zu erwähnen:

PostgreSQL bietet zwei Typen zum Speichern von JSON-Daten: jsonund jsonb. Um effiziente Abfragemechanismen für diese Datentypen zu implementieren, bietet PostgreSQL auch den in Abschnitt 8.14.6 beschriebenen Datentyp jsonpath an .

Die Datentypen jsonund jsonbakzeptieren nahezu identische Wertesätze als Eingabe. Der wesentliche praktische Unterschied besteht in der Effizienz. Der jsonDatentyp speichert eine exakte Kopie des Eingabetextes, die die Verarbeitungsfunktionen bei jeder Ausführung erneut analysieren müssen. während jsonbDaten in ein zerlegt Binärformat , das es etwas langsamer Eingang macht es aufgrund der für Umwandlung Aufwand, aber deutlich schneller Prozess gespeichert ist, da kein neuparsen benötigt wird. jsonbunterstützt auch die Indizierung, was ein erheblicher Vorteil sein kann.

Da der jsonTyp eine exakte Kopie des Eingabetextes speichert, bleiben semantisch unbedeutende Leerzeichen zwischen Token sowie die Reihenfolge der Schlüssel in JSON-Objekten erhalten. Wenn ein JSON-Objekt innerhalb des Werts mehr als einmal denselben Schlüssel enthält, werden alle Schlüssel / Wert-Paare beibehalten. (Die Verarbeitungsfunktionen betrachten den letzten Wert als den operativen Wert.) Im Gegensatz dazu wird jsonbder Leerraum nicht beibehalten, die Reihenfolge der Objektschlüssel wird nicht beibehalten und es werden keine doppelten Objektschlüssel beibehalten. Wenn in der Eingabe doppelte Schlüssel angegeben sind, wird nur der letzte Wert beibehalten.

Im Allgemeinen sollten die meisten Anwendungen es vorziehen, JSON-Daten als zu speichern jsonb, es sei denn, es gibt ganz spezielle Anforderungen, wie z. B. ältere Annahmen zur Reihenfolge der Objektschlüssel.

PostgreSQL erlaubt nur eine Zeichensatzcodierung pro Datenbank. Es ist daher nicht möglich, dass die JSON-Typen starr der JSON-Spezifikation entsprechen, es sei denn, die Datenbankcodierung ist UTF8. Versuche, Zeichen, die nicht in der Datenbankcodierung dargestellt werden können, direkt einzuschließen, schlagen fehl. Umgekehrt sind Zeichen zulässig, die in der Datenbankcodierung, jedoch nicht in UTF8 dargestellt werden können.

Quelle: https://www.postgresql.org/docs/current/datatype-json.html

Dinei
quelle
6

Soweit ich sagen kann,

  • Der derzeit vorhandene hstore (in Postgresql 9.3) ermöglicht nicht das Verschachteln anderer Objekte und Arrays als Werte seiner Schlüssel / Wert-Paare. Ein zukünftiger Hstore-Patch ermöglicht jedoch das Verschachteln. Dieser Patch wird nicht in der Version 9.4 enthalten sein und möglicherweise nicht in Kürze enthalten sein.

  • json, wie es derzeit existiert, erlaubt das Verschachteln, ist jedoch textbasiert und erlaubt keine Indizierung, daher ist es "langsam"

  • jsonb, das mit 9.4 veröffentlicht wird, verfügt über die aktuellen Verschachtelungsfunktionen von json sowie über die GIN / GIST-Indizierung von hstore, sodass es schnell geht

Leute, die an postgresql 9.4 arbeiten, scheinen zu sagen, dass der neue, schnelle jsonb-Typ Leute ansprechen wird, die sich für einen noSQL-Datenspeicher wie MongoDB entschieden hätten, jetzt aber eine relationale Datenbank mit abfragbaren unstrukturierten Daten unter einem Dach kombinieren können

http://www.databasesoup.com/2014/02/why-hstore2jsonb-is-most-important.html

Die Benchmarks von postgresql 9.4 jsonb scheinen mit MongoDB gleichzusetzen oder in einigen Fällen schneller zu sein

http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb

erik swedberg
quelle
6

Ein weiterer wichtiger Unterschied, der in keiner Antwort oben erwähnt wurde, ist, dass es keinen Gleichheitsoperator für den jsonTyp gibt, aber einen für jsonb.

Dies bedeutet , dass Sie nicht verwenden können DISTINCTSchlüsselwort , wenn diese Auswahl json-Typ und / oder andere Felder aus einer Tabelle (können Sie verwenden DISTINCT ONstattdessen, aber es ist nicht immer möglich , da die Fälle wie diesen ).

vlasiak
quelle