2010-11-08 20 views
84

Sto cercando di capire l'equivalente di chiavi e indici esterni nei database KVP o Documento NoSQL. Dal momento che non ci sono tabelle pivotali (per aggiungere chiavi che segnano una relazione tra due oggetti) sono davvero stordito su come si sarebbe in grado di recuperare i dati in un modo che sarebbe utile per le normali pagine web.Come monitorare le relazioni record in NoSQL?

Dire che ho un utente e questo utente lascia molti commenti in tutto il sito. L'unico modo che posso pensare di tenere traccia di che i commenti degli utenti è quello di

  1. Embed loro in oggetto utente (che sembra abbastanza inutile)
  2. Creare e mantenere un valore user_id:comments che contiene un elenco di ogni commento di chiave [commento: 34, commento: 197, ecc ...] in modo che possa recuperarli secondo necessità.

Tuttavia, prendendo il secondo esempio vi sarà presto colpito un muro di mattoni quando lo si utilizza per il monitoraggio altre cose, come una chiave denominata "active_comments" che potrebbero contenere 30 milioni di ID in esso che lo rende costato una tonnellata a interrogare ogni pagina solo per conoscere alcuni commenti attivi recenti. Sarebbe anche molto incline a condizioni di gara poiché molte pagine potrebbero provare ad aggiornarlo allo stesso tempo.

Come si possono tracciare relazioni come le seguenti in un database NoSQL?

  • Tutti i commenti di un utente
  • Tutti i commenti attivi
  • Post con tag [parola chiave]
  • Tutti gli studenti in un club - o tutti i club uno studente è in

Oppure sto pensando a questo in modo errato?

+0

Non c'è un modo per farlo nei database NoSQL, questa domanda è piuttosto un parente a chiedere come vorrei tracciare relazioni in programmi C. – stonemetal

+3

Wow, quindi suppongo che l'hype su NoSQL che sostituisce RDBMS sia impossibile. – Xeoncross

+10

Sì, NoSQL è sicuramente overhyped. Non sto dicendo che le nuove tecnologie non siano utili nelle giuste circostanze, ma è ridicolo pensare che sostituiranno l'RDBMS. Vedi http://en.wikipedia.org/wiki/Hype_cycle –

risposta

124

Tutte le risposte su come memorizzare molti-a-molti associazioni nel "modo NoSQL" ridurre al stessa cosa: memorizzazione dei dati in modo ridondante.

In NoSQL, non si progetta il database in base alle relazioni tra le entità di dati. Progetta il tuo database in base alle query che eseguirai contro di esso. Utilizzare gli stessi criteri che si utilizzerebbero per denormalizzare un database relazionale: se è più importante che i dati abbiano coesione (si pensi ai valori in un elenco separato da virgole invece che in una tabella normalizzata), quindi procedere in questo modo.

Ma questo inevitabilmente si ottimizza per un tipo di query (ad esempio commenti di qualsiasi utente per un dato articolo) a scapito di altri tipi di query (commenti per qualsiasi articolo di un determinato utente). Se la tua applicazione ha la necessità che entrambi i tipi di query siano ugualmente ottimizzati, non dovresti denormalizzare. Allo stesso modo, non è necessario utilizzare una soluzione NoSQL se è necessario utilizzare i dati in modo relazionale.

Esiste un rischio con denormalizzazione e ridondanza che i set di dati ridondanti non verranno sincronizzati tra loro. Questa è chiamata anomalia . Quando si utilizza un database relazionale normalizzato, l'RDBMS può prevenire anomalie. In un database denormalizzato o in NoSQL, diventa responsabilità dell'utente scrivere codice dell'applicazione per prevenire anomalie.

Si potrebbe pensare che sarebbe fantastico per un database NoSQL fare il duro lavoro di prevenire le anomalie per voi. Esiste un paradigma che può farlo: il paradigma relazionale.

+11

"non dovresti usare una soluzione NoSQL se hai bisogno di usare i dati in modo relazionale" - Quindi come fanno gli altri che eseguono NoSQL a farla franca? Come è possibile conoscere tutti i modi in cui si interrogheranno i dati quando si progetta per la prima volta l'applicazione? Esempio Fox, potrei volere commenti recenti, commenti per utente, commenti per tag, commenti per un determinato post, commenti contrassegnati come spam, commenti attivi, commenti più votati, ecc. – Xeoncross

+7

Esattamente - non c'è niente di simile a " funziona semplicemente "come sostengono i sostenitori di NoSQL. O fai un po 'di analisi in anticipo per la tua modellazione dei dati relazionali, o fai un mucchio di analisi in anticipo per le tue query con priorità più alta, o esegui un sacco di refactoring costoso durante il progetto mentre scopri quali parti del tuo design non ho avuto abbastanza analisi in anticipo. –

+0

@Xeoncross Sto capendo anche questo problema. Dai un'occhiata agli indici secondari. Generalmente, NoSQL crea indici secondari per soddisfare diversi casi di utilizzo aziendale. Tuttavia, è preferito un numero minore di indici secondari. –

4
  1. utente: UserID: commenti è un approccio ragionevole - pensare ad esso come l'equivalente di un indice di colonna in SQL, con il requisito aggiunto che non si può interrogare sulle colonne non indicizzati.

  2. Qui è dove devi pensare alle tue esigenze. Una lista con 30 milioni di articoli non è irragionevole perché è lenta, ma perché non è pratico fare nulla con essa. Se il tuo reale requisito è quello di visualizzare alcuni commenti recenti, è meglio tenere una lista molto breve che viene aggiornata ogni volta che viene aggiunto un commento - ricorda che NoSQL non ha requisiti di normalizzazione. Le condizioni di gara sono un problema con gli elenchi in un archivio di valori chiave di base, ma in genere la tua piattaforma supporta gli elenchi correttamente, puoi fare qualcosa con i blocchi o non ti interessa effettivamente gli aggiornamenti non riusciti.

  3. Come per i commenti degli utenti - creare una parola chiave di indice: i messaggi

  4. Più dello stesso - probabilmente un elenco di club come una proprietà di studente e un indice su quel campo per ottenere tutti i membri di un club

+0

Quindi, praticamente tutto ha solo bisogno di liste? Sembra che ci dovrebbe essere un approccio più sofisticato rispetto al semplice tenere traccia delle stringhe di id manualmente. Per uno, puoi solo andare così lontano prima che diventino grandi per essere utili. Inoltre, i principali progetti poster-child della tecnologia NoSQL (MongoDB, CouchDB, Membase, ecc.) Sono tutti progetti nuovi, quindi forse ho solo bisogno di dare loro più tempo per trovare un modo migliore per tenere traccia delle relazioni. – Xeoncross

+0

Se si utilizza NoSQL (archivi dati non relazionali AKA) è necessario smettere di pensare in termini relazionali. L'approccio utilizzato differirà tra le piattaforme, ma l'idea di base che devi gestire gli indici è abbastanza universale. Gli esempi di relazioni che hai fornito sono modellati in due modi diversi in NoSQL: 1) Archiviazione: diversamente da SQL, le colonne possono avere valori multipli/complessi, quindi l'oggetto figlio è solo una parte dell'oggetto padre. 2) Ricerca - Le lunghe liste sono in realtà un requisito per la ricerca, il che significa indicizzazione: è possibile utilizzare un semplice elenco personalizzato o un motore di ricerca più completo. –

3

l'approccio CouchDB suggeriscono di emettere adeguate classi di roba in fase di mappa e riassumerla nel ridurre .. Così si potrebbe mappare tutti i commenti ed emettono 1 per l'utente dato e successivamente stampare unici.Richiederebbe tuttavia un sacco di spazio su disco per creare viste permanenti di tutti i dati rintracciabili in couchDB. btw hanno anche questa pagina wiki sulle relazioni: http://wiki.apache.org/couchdb/EntityRelationship.

Riak d'altra parte ha uno strumento per costruire relazioni. È un collegamento. È possibile inserire l'indirizzo di un documento collegato (qui commento) nel documento 'root' (qui documento utente). Ha un trucco. Se è distribuito, può essere modificato contemporaneamente in molte posizioni. Ciò causerà conflitti e di conseguenza un enorme albero di clock vettoriale:/... non così male, non così buono.

Riak ha anche un altro "meccanismo". Ha uno spazio per i nomi dei tasti su 2 livelli, chiamato benna e chiave. Così, per esempio studenti, Se abbiamo Club A, B e C e studente StudentX, studenty si potrebbe mantenere la seguente convenzione:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true } 

e leggere relazione solo le chiavi di elenco in date secchi. Cosa c'è che non va? È dannatamente lento. I bucket di elenco non hanno mai avuto priorità per riak. Sta diventando sempre meglio. btw. non sprechi memoria perché questo esempio {true} può essere collegato al profilo completo singolo di StudentX o Y (qui i conflitti non sono possibili).

Come lo vedi NoSQL! = NoSQL. È necessario esaminare l'implementazione specifica e testarla da soli.

Menzionato prima che i negozi di colonne sembrino adatti per le relazioni .. ma tutto dipende dalle vostre esigenze A e C e P;) Se non avete bisogno di A e avete meno di byte Peta lasciatelo, andare avanti con MySql o Postgres.

buona fortuna

+1

Riak ha recentemente rilasciato la versione 1.0, che aggiunge il supporto per gli indici secondari quando si utilizza il backend di LevelDB. Caratteristica molto preziosa. –

0

Penso che RavenDB offra una buona soluzione a questo problema con l'indicizzazione. Le informazioni nella pagina principale http://ravendb.net/ spiegano il concetto abbastanza bene da poter creare qualcosa di analogo per la tua tecnologia.

1

Hai

"user": { 
    "userid": "unique value", 
    "category": "student", 
    "metainfo": "yada yada yada", 
    "clubs": ["archery", "kendo"] 
} 

"comments": { 
    "commentid": "unique value", 
    "pageid": "unique value", 
    "post-time": "ISO Date", 
    "userid": "OP id -> THIS IS IMPORTANT" 
} 

"page": { 
    "pageid": "unique value", 
    "post-time": "ISO Date", 
    "op-id": "user id", 
    "tag": ["abc", "zxcv", "qwer"] 
} 

Bene in un database relazionale la cosa normale da fare sarebbe in una relazione uno-a-molti è quello di normalizzare i dati. Questa è la stessa cosa che faresti anche in un database NoSQL. Basta indicizzare i campi con cui verranno recuperate le informazioni.

Per esempio, gli indici importanti per voi sono

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

Se stanno usando NosDB (A .NET based NoSQL Database with SQL support) le vostre domande saranno come

SELECT * FROM Comments WHERE userid = ‘That user’; 

SELECT * FROM Comments WHERE pageid = ‘That user’; 

SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1'); 

SELECT * FROM Page WHERE tag = 'kendo' 

Controllare tutti i tipi di query supportati dal loro SQL cheat sheet o dalla documentazione.