JSONB mit Indexierung vs. hstore

28

Ich versuche, mich für das Design der Datenbank zu entscheiden, wobei zu diesem Zeitpunkt möglichst wenige Annahmen (hinsichtlich der tatsächlichen Entwicklung der Web-App) getroffen werden müssen.

Um zu verstehen, dass JOINS teuer sind, betrachte ich als ersten Schritt eine kleine Anzahl monolithischer Tabellen im Gegensatz zu einer großen Anzahl normalisierter kleinerer Tabellen. Als zweiter Punkt bin ich verwirrt zwischen der Verwendung von hstore vs. regulären Tabellen vs. JSONB (mit GiST-Indizierung).

AFAIK (bitte zögern Sie nicht zu korrigieren):

  1. Im Allgemeinen ist bekannt, dass hstore in Postgres eine bessere Leistung erbringt als andere Datentypen. Diese Präsentation von FOSDEM PGDAY enthält einige interessante Statistiken (in der zweiten Hälfte der Folien). https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. Ein Vorteil von hstore ist die schnelle Indizierung (GiN oder GiST). Mit JSONB können die Indizierungen GiN und GiST jedoch auch auf JSON-Daten angewendet werden.

  3. Dieser Blog von einem professionellen im zweiten Quadranten sagt : „An dieser Stelle lohnt es sich wahrscheinlich hstore Verwendung mit jsonb in allen neuen Anwendungen zu ersetzen“ (scrollen bis zum Ende): http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary -jsonhstore-dynamic-columns /

Ich möchte mich also für Folgendes entscheiden:

  1. Für den (strukturierten) Hauptteil der Daten: Sollte er in ein paar relationalen Tabellen (relativ groß mit vielen Spalten) abgelegt werden, oder sollte er eine Anzahl von Schlüsselwertspeichern sein, die hstore verwenden?
  2. Sollten sich die Ad-hoc-Daten (vom Benutzer eingegebene / unstrukturierte Daten) in JSON oder in Ad-hoc-Schlüsselwertspeichern in hstore befinden (wobei die Schlüssel in einer der relationalen Haupttabellen gespeichert sind)?
Yogesch
quelle
7
Joins sind nicht teuer. Wer hat es dir gesagt? Da sich das gesamte Konzept relationaler Datenbanken im Grunde genommen um Verknüpfungen dreht (aus praktischer Sicht), können diese Produkte sehr gut verknüpft werden. Die normale Denkweise beginnt mit richtig normalisierten Strukturen und geht in ausgefallene Denormalisierungen und ähnliches über, wenn die Performance dies auf der Leseseite wirklich benötigt. JSON(B)und hstore(und EAV) eignen sich für Daten mit unbekannter Struktur.
22.
6
@Yogesch diese Links enthalten einige interessante und widersprüchliche Dinge :) Aus moralischen Gründen sieht es so aus, als ob MySQL bei Joins schlecht ist (war) und NoSQL-Leute neigen dazu, diesen Begriff ohne tatsächliche Faktengrundlage zu verallgemeinern. Auf der anderen Seite reagieren Aaron und Max sensibel auf dieses P-Wort - seine weit verbreitete Verwendung zeigt, wie Nicht-Muttersprachler (auch ich) gerne das falsche Wort verwenden.
Dezso
4
@Yogesch Ich bin mir realistisch sicher, dass es im Internet eine Quelle gibt, die alles "beweist", so wie jeder religiöse Text verwendet werden kann, um Gräueltaten zu rechtfertigen (wie es in der Geschichte dramatisch gezeigt wird). Es ist wahr, je weniger Arbeit Sie erledigen, desto weniger kostet es, aber es gibt immer einen Kompromiss .
Erik
4
@Yogesch: Das Vermeiden von Verknüpfungen ist wichtig für Vorgänge mit hohem Lesezugriff, bei denen Sie das Datenzugriffsmuster im Voraus kennen, damit Sie alle benötigten Daten sicher in einer einzigen Zeile zusammenfassen können. Dies macht jedoch andere Verknüpfungen möglicherweise teurer. Wer möchte sagen, dass Sie die Daten nicht auf viele verschiedene Arten verknüpfen müssen, um verschiedene Fragen zu beantworten? Jetzt gehen wir einfach auf die Theorie der relationalen Datenmodellierung ein ...
Chris
5
@Yogesch In meiner Praxis ist der Engpass bei Datenbanken selten der Arbeitsspeicher oder die CPU, sondern die E / A. Auf diese Weise ist es immer noch wichtig, das Speichern redundanter Daten zu vermeiden. Wenn Sie Ihre Daten immer nur auf eine Weise sehen, ist dies möglicherweise den Preis wert. Wenn nicht, sind Sie mit einem sperrigen und hochgradig unflexiblen Datenblock da.
Dezso

Antworten:

41

Relationale Datenbanken sind auf Verknüpfungen ausgelegt und darauf optimiert.

Verwenden Sie ein normalisiertes Design, es sei denn, Sie haben einen guten Grund , ein normalisiertes Design nicht zu verwenden.

jsonbund Dinge wie hstoresind nützlich, wenn Sie ein normalisiertes Datenmodell nicht verwenden können, z. B. wenn sich das Datenmodell schnell ändert und benutzerdefiniert ist.

Wenn Sie es relational modellieren können, modellieren Sie es relational. Wenn dies nicht möglich ist, ziehen Sie JSON in Betracht. Wenn Sie sich für JSON / JSONB / HSTORE entscheiden, wählen Sie im Allgemeinen JSONB, es sei denn, Sie haben einen Grund, dies nicht zu tun.

Das habe ich in meinem Blogbeitrag gesagt , der genau dieses Thema anspricht. Bitte lies den ganzen Beitrag . Der Absatz, den Sie zitiert haben, weist darauf hin, dass Sie bei der Auswahl einer dynamischen Struktur jsonb anstelle von hstore wählen sollten. Der Rest des Blogposts handelt jedoch davon, warum Sie es normalerweise vorziehen sollten, relational zu modellieren, wenn Sie können.

So. Modellieren Sie den Hauptstrukturteil relational. Wenn die Tabellen wirklich breit sind und viele Spalten enthalten, kann dies ein Zeichen dafür sein, dass eine weitere Normalisierung erforderlich ist. Hab keine Angst vor Verbindungen. Lerne, Joins zu lieben. Das Verknüpfen vieler kleiner Tabellen ist häufig schneller als das Abfragen und Verwalten großer denormalisierter Tabellen. Denormalisieren Sie nur, wenn dies für bestimmte Fälle erforderlich ist, vorzugsweise über materialisierte Ansichten. Tun Sie dies jedoch erst, wenn Sie wissen, dass Sie ein konkretes Problem lösen müssen.

Verwenden Sie für vom Benutzer bereitgestellte Daten, die frei und unstrukturiert sind, jsonb. Es sollte genauso gut funktionieren wie hstore, ist aber flexibler und einfacher zu bearbeiten.

Eine wichtige Sache zu verstehen: GiST- und GIN-Indizes, wie sie in jsonb verwendet werden, sind im Allgemeinen viel weniger effizient als ein einfacher B-Tree-Index. Sie sind flexibler, aber ein B-Tree-Index für eine normale Spalte ist fast immer viel, viel schneller.

Craig Ringer
quelle
Vielen Dank Craig, jetzt habe ich ein viel besseres Verständnis und weiß, was zu tun ist. Eine weitere Frage: Wenn ich Likes oder Follower in einem zweispaltigen Format speichere (post_id und user_id für Likes ), ist es besser, eine relationale Tabelle mit zwei Spalten oder einen hstore zu verwenden? (Ich habe nichts dagegen, daraus eine neue Frage zu machen)
Yogesch
5
@Yogesch Es klingt wie eine m: n-Join-Tabelle nach Moorstandard mit einem konsistenten und stabilen Format. Die Frage sollte immer lauten: "Gibt es einen guten Grund, warum ich dies nicht auf die für diesen speziellen Fall übliche relationale Weise tun sollte ?".
Craig Ringer
hstoreist veraltet. Verwenden Sie jsonb.
danger89
2
@ danger89 Eigentlich ist es nicht offiziell veraltet, obwohl ich glaube, dass es keinen Grund mehr gibt, es zugunsten von jsonb zu verwenden. Auf jeden Fall ... das geht irgendwie daneben. Die Frage ist, ob relational modelliert oder ein strukturierter Datentyp verwendet werden soll.
Craig Ringer