Utilizzando MongoDB e PostgreSQL insieme


25

Il mio progetto attuale è essenzialmente una corsa al sistema di gestione dei documenti del mulino.

Detto questo, ci sono alcune rughe (sorpresa, sorpresa). Mentre alcune delle rughe sono abbastanza specifiche per il progetto, credo che siano emerse alcune osservazioni e domande generali che non hanno una risposta canonica (che potrei trovare, comunque) e che sono applicabili a un dominio problematico più ampio . C'è molto qui e non sono sicuro che sia adatto al formato di domande e risposte StackExchange, ma penso che a) una domanda responsabile eb) abbastanza non specifico da poter essere di beneficio alla comunità. Alcune delle mie considerazioni sono specifiche per me, ma penso che la domanda potrebbe essere utile a chiunque debba affrontare la decisione su SQL vs NoSQL vs entrambi.

Lo sfondo:

L'app Web che stiamo creando contiene dati di natura chiaramente relazionale, nonché dati orientati ai documenti. Vorremmo avere la nostra torta e mangiarla anche noi.

TL; DR: Penso che il n. 5 sotto superi il test dell'olfatto. Fai? Qualcuno ha esperienza con una tale integrazione di SQL e NOSQL in una singola applicazione? Ho cercato di elencare tutti i possibili approcci a questa classe di problemi nel seguito. Ho perso un'alternativa promettente?

complessità:

  • Esistono molte diverse classi di documenti. I requisiti richiedono già dozzine di documenti diversi. Questo numero aumenterà sempre e solo. Il caso migliore sarebbe quello in cui potremmo sfruttare un semplice linguaggio specifico di dominio, generazione di codice e uno schema flessibile in modo che gli esperti di dominio possano gestire l'aggiunta di nuove classi di documenti senza l'intervento di DBA o programmatori. (Nota: già consapevole che stiamo vivendo la Decima Regola di Greenspun )
  • L'integrità delle precedenti scritture riuscite è un requisito centrale del progetto. I dati saranno fondamentali per l'azienda. La semantica ACID completa sulle scritture può essere sacrificata a condizione che le cose che vengono scritte con successo rimangano scritte.
  • I documenti sono essi stessi complessi. Il documento prototipo nel nostro caso specifico richiederà l'archiviazione di oltre 150 parti distinte di dati per istanza del documento. Il caso patologico potrebbe essere un ordine di grandezza peggiore, ma certamente non due.
  • Una singola classe di documenti è un obiettivo mobile soggetto ad aggiornamenti in un secondo momento.
  • Ci piace il materiale gratuito che riceviamo da Django quando lo colleghiamo a un database relazionale. Vorremmo mantenere i freebies senza dover saltare indietro di due versioni di Django per usare la forcella django-nonrel. Scaricare l'ORM interamente è preferibile al downgrade a 1.3.

In sostanza, si tratta di un miscuglio di dati relazionali (le tue cose tipiche delle app web come utenti, gruppi, ecc., Così come i metadati dei documenti che dovremo essere in grado di tagliare e tagliare con query complesse in tempo reale) e dati dei documenti (ad es. le centinaia di campi per i quali non abbiamo interesse a unirci o interrogare - il nostro unico caso d'uso per i dati sarà quello di mostrare il singolo documento in cui sono stati inseriti).

Volevo fare un controllo di integrità (se controlli la mia cronologia dei post, sono piuttosto esplicito sul fatto che non sono un DBA) sul mio metodo preferito, nonché elencare tutte le opzioni che ho trovato per gli altri a risolvere problemi sostanzialmente simili che coinvolgono dati sia relazionali che non relazionali.

Soluzioni proposte:

1. Una tabella per classe di documenti

Ogni classe di documenti ottiene la propria tabella, con colonne per tutti i metadati e dati.

vantaggi:

  • È in gioco il modello di dati SQL standard.
  • I dati relazionali vengono gestiti nel miglior modo possibile. Denormalizzeremo più tardi se necessario.
  • L'interfaccia di amministrazione integrata di Django è a suo agio nell'introspezione di queste tabelle e l'ORM può vivere felicemente con il 100% dei dati pronti all'uso.

svantaggi:

  • Incubo di manutenzione. Dozzine (centinaia?) Di tabelle con (decine di?) Migliaia di colonne.
  • Logica a livello di applicazione responsabile di decidere esattamente su quale tabella scrivere. Rendere il nome della tabella un parametro per una query puzza.
  • Fondamentalmente tutte le modifiche alla logica aziendale richiedono modifiche allo schema.
  • I casi patologici potrebbero richiedere lo striping dei dati per singoli moduli su più tabelle (vedi: Qual è il numero massimo di colonne in una tabella PostgreSQL? ).
  • Probabilmente avremmo bisogno di trovare un vero DBA onesto a Dio che senza dubbio finisca per odiare la vita e noi.

2. Modellazione EAV

C'è solo una tabella dei campi. La modellazione di entità-attributo-valore è già ben compresa. L'ho incluso per completezza. Non credo che nessun nuovo progetto avviato nel 2013 sarebbe apposta con un approccio EAV.

vantaggi:

  • Facile da modellare.

svantaggi:

  • Più difficile da interrogare.
  • Il livello DB non ha più una rappresentazione diretta di ciò che costituisce un oggetto a livello di app.
  • Perderemmo il controllo dei vincoli a livello di DB.
  • Il numero di righe su una tabella aumenterà 100s-1000s di volte più velocemente. Probabile punto di dolore futuro, dal punto di vista delle prestazioni.
  • Indicizzazione limitata possibile.
  • Lo schema DB non ha senso per quanto riguarda ORM. Le batterie incluse nel materiale delle app Web vengono conservate ma i modelli di dati personalizzati richiedono query personalizzate.

3. Utilizzare i campi hstore o json di PostgreSQL

Ognuno di questi tipi di campi farebbe il trucco per la memorizzazione di dati schematici nel contesto di un DB relazionale. L'unica ragione per cui non salto a questa soluzione è immediatamente è relativamente nuovo (introdotto nella versione 8.4, quindi non che nuovo), Io ho zero precedente esposizione ad esso e io sono sospettoso. Mi sembra sbagliato per gli stessi motivi per cui mi sentirei a disagio nel lanciare tutti i miei dati belli e facilmente normalizzati in Mongo, anche se Mongo è in grado di gestire i riferimenti tra i documenti.

vantaggi:

  • Otteniamo i vantaggi di Django ORM e della gestione integrata delle sessioni e delle autorizzazioni.
  • Tutto rimane in un backend che abbiamo già utilizzato con successo su altri progetti.

svantaggi:

  • Nessuna esperienza con questo, personalmente.
  • Non sembra una funzionalità molto utilizzata. Sembra che vengano raccomandati un po 'alle persone che guardano alle soluzioni NOSQL, ma non vedo molte prove che vengano scelte. Questo mi fa pensare che mi manchi qualcosa.
  • Tutti i valori memorizzati sono stringhe. Perdita del controllo dei vincoli a livello di DB.
  • I dati nell'hstore non verranno mai mostrati all'utente a meno che non visualizzino specificamente un documento, ma saranno i metadati memorizzati in più colonne standard. Stiamo battendo quei metadati e temo che gli hstore piuttosto grandi che creeremo potrebbero avere degli svantaggi nelle prestazioni.

4. Orientamento completo al documento

Rendi tutti i documenti (in senso MongoDB). Crea una singola raccolta di tipi Documente chiamala un giorno. Porta anche in mongo tutti i dati periferici (inclusi i dati sugli account utente, i gruppi, ecc.). Questa soluzione è ovviamente migliore della modellazione EAV, ma mi sembra sbagliato per lo stesso motivo per cui # 3 si sentiva sbagliato: entrambi hanno voglia di usare anche il martello come cacciavite.

vantaggi:

  • Non è necessario modellare i dati in anticipo. Prendi una raccolta con documenti di tipo Documente chiamala un giorno.
  • Conosciute buone caratteristiche di ridimensionamento, se la raccolta dovesse crescere per comprendere milioni o addirittura miliardi di documenti.
  • Il formato JSON (BSON) è intuitivo per gli sviluppatori.
  • A quanto ho capito (che è solo vagamente a questo punto), essendo paranoico per quanto riguarda il livello di preoccupazione di scrittura, anche una singola istanza può fornire una sicurezza dei dati piuttosto forte in caso di qualsiasi cosa fino a un crash del disco rigido.

svantaggi:

  • L'ORM è fuori dalla finestra per il baule Django. Freebies che escono dalla finestra con esso: il framework auth, il framework delle sessioni, l'interfaccia di amministrazione, sicuramente molte altre cose.
  • È necessario utilizzare le funzionalità di riferimento di mongo (che richiedono più query) o denormalizzare i dati. Non solo perdiamo omaggi che abbiamo ottenuto da Django, ma perdiamo anche omaggi come JOIN che abbiamo dato per scontato in PostgreSQL.
  • Sicurezza dei dati. Quando si legge su MongoDB, sembra che ci sia sempre almeno una persona che si riferisce a come salverà e perderà i tuoi dati. Non citano mai un evento particolare e potrebbe essere solo un colpo di frusta o semplicemente legato al vecchio fuoco predefinito e dimenticare la preoccupazione per la scrittura, ma mi preoccupa ancora. Ovviamente utilizzeremo una strategia di backup abbastanza paranoica (se i dati vengono danneggiati in modo silenzioso, ovviamente potrebbe non essere rilevante ...).

5. PostgreSQL e MongoDB

I dati relazionali vanno nel database relazionale e i dati del documento vanno nel database orientato al documento. La documentstabella nel database relazionale contiene tutti i dati di cui potremmo aver bisogno per indicizzare, suddividere e tagliare, nonché un ObjectId MongoDB che utilizzeremmo quando avessimo bisogno di cercare i valori effettivi dei campi nei documenti. Non saremmo in grado di utilizzare l'ORM o l'amministratore integrato per i valori dei documenti stessi, ma non è una grande perdita poiché l'intera app è sostanzialmente un'interfaccia di amministrazione per i documenti e probabilmente avremmo dovuto personalizzare quella parte specifica dell'ORM a un livello inaccettabile per farlo funzionare nel modo che ci serve.

vantaggi:

  • Ogni backend fa solo ciò in cui è bravo.
  • I riferimenti tra i modelli vengono conservati senza richiedere più query.
  • Manteniamo le batterie che Django ci ha fornito per quanto riguarda utenti, sessioni, ecc.
  • È necessaria solo una documentstabella, indipendentemente dal numero di diverse classi di documenti creati.
  • I dati del documento meno frequentemente interrogati sono fortemente separati dai metadati molto più spesso interrogati.

svantaggi:

  • Il recupero dei dati del documento richiederà 2 query sequenziali, prima sul DB SQL e poi sul MongoDB (anche se non è peggio che se gli stessi dati fossero stati archiviati in Mongo e non denormalizzati)
  • La scrittura non sarà più atomica. Una scrittura contro un singolo documento Mongo è garantita come atomica e PG ovviamente può garantire l'atomicità, ma garantire l'atomicità della scrittura su entrambi richiederà logica applicativa, senza dubbio con una penalità di prestazioni e complessità.
  • Due backend = due lingue di query = due programmi diversi con requisiti di amministrazione diversi = due database in lizza per la memoria.

Vorrei una colonna con un JSONtipo di dati. Non aver paura di usare nuove funzionalità in Postgres: il team di Postgres non rilascia funzionalità che non sono stabili. E 9.2 non è così nuovo in realtà). Inoltre, puoi utilizzare le nuove funzionalità JSON in 9.3 una volta che è lì. Se si elaborano sempre completamente i documenti nel codice dell'applicazione (anziché utilizzare SQL), è possibile anche archiviare JSON in una textcolonna normale .
a_horse_with_no_name

Ai potenziali risponditori: non esitate a fornire una risposta! Poiché questa domanda è sopravvissuta abbastanza a lungo senza una risposta "perfetta", tuttavia, intendo rispondere alla domanda con un postmortem completo dell'esperienza una volta implementata e passata alla produzione. Potrebbe essere un anno in futuro, ma non preoccuparti: l'OP consegnerà. Mi aspetto che sia ciò che coloro che hanno favorito / votato a favore di questa particolare domanda troverebbero più utile: la verifica del funzionamento o una spiegazione di quali blocchi stradali hanno ucciso l'opzione side-by-side.
Chucksmash,

2
@chucksmash. Sei andato con il n. 5, dopo tutto? Come sei riuscito a implementare entrambi i dbs? Quali strumenti hai usato? Se no, perché?
xpanta,

@chucksmash Sto ancora aspettando il feedback che hai promesso.
Bhashit Parikh,

@chucksmash OP non ha consegnato ... :(
Albert Rothman

Risposte:


13

Alcuni pensieri....

In genere non si desidera archiviare pezzi di informazioni strettamente correlate in sistemi diversi. Le possibilità che le cose vadano fuori sincrono sono significative e ora invece di un problema tra le mani ne hai due. Una cosa che puoi fare con Mongo è però usarlo per pipeline dentro o fuori i tuoi dati. La mia preferenza è di mantenere tutto in PostgreSQL nella misura del possibile. Tuttavia, vorrei notare che farlo richiede davvero una conoscenza approfondita della programmazione PostgreSQL e non è per i negozi che non sono disposti a dedicarsi all'uso di funzionalità avanzate. Vedo un insieme un po 'diverso di opzioni rispetto a te. Poiché la mia preferenza non è qualcosa che vedo elencato, te lo darò.

Probabilmente puoi separare i tuoi metadati in dati comuni, dati richiesti per le classi e dati del documento. A questo proposito avresti una tabella di catalogo generale con le informazioni comuni di base più una tabella per classe. In questa tabella avresti un campo hstore, json o xml che memorizzerebbe il resto dei dati insieme a colonne in cui stai memorizzando dati che devono essere vincolati in modo significativo. Ciò ridurrebbe ciò che è necessario inserire in queste tabelle per classe, ma consentirebbe di sfruttare i vincoli nel modo desiderato. Le tre opzioni hanno problemi diversi e vale la pena considerare separatamente:

hstore è relativamente limitato ma utilizzato anche da molte persone. Non è estremamente nuovo ma è solo un archivio chiave / valore ed è incapace di strutture di dati nidificati, a differenza di json e xml.

JSON è abbastanza nuovo e in questo momento non fa molto. Questo non significa che non puoi farci molto, ma non farai molto fuori dagli schemi. Se lo fai puoi aspettarti di fare una quantità significativa di programmazione, probabilmente in plv8js o, se vuoi rimanere con ambienti più vecchi, plperlu o plpython. jsonè meglio supportato in 9.3 sebbene almeno nelle attuali istantanee di sviluppo, quindi quando verrà rilasciata quella versione le cose andranno meglio.

xml è il migliore supporto dei tre, con il maggior numero di funzionalità e la più lunga cronologia di supporto. Poi di nuovo, è XML .....

Tuttavia, se decidi di utilizzare Mongo e PostgreSQL insieme, tieni presente che PostgreSQL supporta il commit a 2 fasi, il che significa che puoi eseguire le operazioni di scrittura, quindi eseguire PREPARE TRANSACTIONe in questo caso le tue scritture atomiche in Mongo. Se ciò ha esito positivo, è possibile COMMITin PostgreSQL.


1
Questi sono tutti ottimi suggerimenti. Avevo già parlato di usare hstore / json in precedenza (e avevo scontato silenziosamente xml, perché, beh, xml) ma non avevo pensato di usarli nel modo che consigli. Inoltre, il suggerimento per il commit della fase 2 di Postgres è l'oro. Non avevo idea che esistesse. Grazie per gli ottimi suggerimenti.
Chucksmash,

Il commit a 2 fasi è davvero l'oro. Rende molto fattibile l'uso di un NoSQL in tandem. Soprattutto se i dati tra i 2 DB si
collegano

0

È possibile impostare un motore di query come Presto o Dremio per unire i dati residenti in MongoDB e Postgres con una singola query. Entrambi hanno connettori per ciascuno di questi database (vedere i documenti qui e qui ) e propongono, rispettivamente, di eseguire "SQL su qualsiasi cosa" e "unire qualsiasi cosa".

Per testare Presto, è possibile distribuire un piccolo cluster su AWS EMR con Hadoop, Hive e Presto (aggiungere tonalità se non si desidera utilizzare la riga di comando), funziona dalla casella - assicurarsi di seguire queste istruzioni per configurare i connettori . Hive non è strettamente necessario, ma con esso puoi creare tabelle usando il risultato dei join tra Mongo e Postgres (controlla questa pagina per esempi). Esiste anche una versione a pagamento sul mercato , che è (presumibilmente) fortemente ottimizzata e ha una prova di 30 giorni.

Non ho usato Dremio, ma ci sono anche alcuni semplici modi per distribuirlo su AWS, Azure o in locale. Hanno alcuni corsi online sul loro sito Web , con accesso a un "laboratorio virtuale" che è possibile utilizzare per seguire le lezioni gratuitamente.

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.