JSONB con indicizzazione vs. hstore


28

Sto provando a decidere la progettazione del database, con il minor numero di ipotesi (riguardo a come si evolve effettivamente l'app Web) in questa fase.

Come primo passo, comprendendo che i JOIN sono costosi, sto prendendo in considerazione un piccolo numero di tabelle monolitiche rispetto a un gran numero di tabelle più piccole normalizzate. Come secondo punto, sono confuso tra l'utilizzo di tabelle hstore vs. tabelle normali e JSONB (con indicizzazione GiST).

AFAIK (non esitate a correggere):

  1. Generalmente, in Postgres, hstore ha prestazioni migliori rispetto ad altri tipi di dati. Questa presentazione di FOSDEM PGDAY ha alcune statistiche interessanti (nella seconda metà delle diapositive). https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. Un vantaggio con hstore è l'indicizzazione rapida (GiN o GiST). Tuttavia, con JSONB, l'indicizzazione GiN e GiST può essere applicata anche ai dati JSON.

  3. Questo blog di un professionista del 2 ° quadrante dice "A questo punto probabilmente vale la pena sostituire l'uso di hstore con jsonb in tutte le nuove applicazioni" (scorrere fino alla fine): http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary -jsonhstore-dynamic-colonne /

Quindi vorrei decidere quanto segue:

  1. Per la parte principale (strutturata) dei dati: dovrebbe andare in un paio di tabelle relazionali (relativamente grandi con molte colonne) o dovrebbe essere un numero di archivi di valori-chiave che usano hstore?
  2. Per i dati ad hoc (forniti dall'utente / non strutturati), dovrebbero essere negli archivi di valori chiave JSON o ad hoc in hstore (con le chiavi archiviate in una delle principali tabelle relazionali)?

7
Le iscrizioni non sono costose. Chi te lo ha detto? Poiché in sostanza l'intero concetto di database relazionali ruota attorno ai join (da un punto di vista pratico), questi prodotti sono molto bravi a unirsi. Il modo normale di pensare è iniziare con strutture adeguatamente normalizzate e entrare in fantasiose denormalizzazioni e cose simili quando la performance ha davvero bisogno sul lato della lettura. JSON(B)e hstore(e EAV) sono utili per i dati con struttura sconosciuta.
dezso

6
@Yogesch quei collegamenti contengono alcune cose interessanti e selvaggiamente contraddittorie :) Dal punto di vista morale, sembra che MySQL sia (era) cattivo nei join e che le persone NoSQL tendano a generalizzare questa nozione senza alcuna effettiva base fattuale. D'altra parte, Aaron e Max sono sensibili a quella parola-p - il suo ampio uso mostra come chi non è madrelingua (me compreso) usa felicemente la parola sbagliata.
dezso,

4
@Yogesch realisticamente sono sicuro che ci sia una fonte su Internet per "provare" qualsiasi cosa, proprio come qualsiasi testo religioso può essere usato per giustificare le atrocità (come mostrato drammaticamente nella storia). È vero meno lavoro fai meno costi, ma c'è sempre qualche compromesso .
Erik,

4
@Yogesch: evitare i join è importante per le operazioni di lettura pesante in cui si conosce in anticipo il modello di accesso ai dati e quindi è possibile inserire in modo sicuro tutti i dati necessari in una singola riga. Tuttavia, ciò rende gli altri join potenzialmente più costosi. Chi può dire che non sarà necessario unire i dati in molti modi diversi per rispondere a varie domande? Ora discenderemo semplicemente nella teoria della modellizzazione dei dati relazionali ...
Chris,

5
@Yogesch Nella mia pratica, con i database il collo di bottiglia è raramente la RAM o la CPU ma è I / O - in questo modo evitare di archiviare dati ridondanti è ancora una cosa importante. Come dice Chris, se vedi sempre i tuoi dati in un solo modo, questo potrebbe valere il prezzo. Altrimenti, ci sei con una massa di dati ingombranti e altamente non flessibili.
dezso

Risposte:


41

I database relazionali sono progettati attorno ai join e ottimizzati per farli bene.

A meno che tu non abbia una buona ragione per non usare un disegno normalizzato, usa un disegno normalizzato.

jsonbe cose del genere hstorevanno bene quando non è possibile utilizzare un modello di dati normalizzato, come quando il modello di dati cambia rapidamente e viene definito dall'utente.

Se è possibile modellarlo relazionalmente, modellarlo relazionalmente. Se non puoi, considera json ecc. Se scegli tra json / jsonb / hstore, generalmente scegli jsonb a meno che tu non abbia un motivo per non farlo.

Questo è quello che ho detto nel mio post sul blog , che affronta proprio questo argomento. Si prega di leggere l'intero post . Il paragrafo che hai citato sottolinea che se stai scegliendo una struttura dinamica dovresti scegliere jsonb su hstore, ma il resto del post sul blog spiega perché dovresti preferire modellare relazionalmente se puoi.

Così. Modella la parte strutturata principale a livello relazionale. Se le tabelle sono davvero ampie con molte colonne, questo potrebbe essere un segno che è necessaria un'ulteriore normalizzazione. Non aver paura dei join. Impara ad amare i join. Unire molte piccole tabelle sarà spesso più veloce che interrogare e mantenere grandi tabelle denormalizzate. Denormalizza solo se è necessario per casi specifici, e preferibilmente tramite viste materializzate ... ma non farlo fino a quando non sai che è necessario e hai un vero problema concreto da risolvere.

Per i dati forniti dagli utenti che sono a mano libera e non strutturati, utilizzare jsonb. Dovrebbe funzionare così come hstore, ma è più flessibile e più facile da lavorare.

Una cosa rilevante da capire: gli indici GiST e GIN come quelli usati su jsonb sono generalmente molto meno efficienti di un semplice indice b-tree. Sono più flessibili, ma un indice b-tree su una colonna normale sarà quasi sempre molto, molto più veloce.


Mille grazie Craig, ora ho una comprensione molto migliore e so cosa fare. Una domanda di follow-up: se sto memorizzando qualcosa come like o follower in un formato a due colonne (post_id e user_id, per like ), è meglio usare una tabella relazionale con due colonne o un hstore? (Non mi dispiace trasformarlo in una nuova domanda)
Yogesch,

5
@Yogesch Sembra una tabella di join m: n standard bog con un formato coerente e stabile. La domanda dovrebbe essere sempre "c'è una buona ragione per cui non dovrei farlo nel solito modo relazionale per questo caso particolare?".
Craig Ringer,

hstoreè deprecato. Usa jsonb.
danger89,

2
@ danger89 In realtà, non è formalmente deprecato, anche se non credo ci sia motivo di usarlo più a favore di JSONB. In ogni caso ... è un po 'come perdere il punto. La domanda è se modellare in modo relazionale o usare un tipo di dati strutturato.
Craig Ringer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.