2010-03-29 12 views
45

Farò un'applicazione con molti articoli simili (milioni), e vorrei memorizzarli in un database MySQL, perché mi piacerebbe fare molte statistiche e cercare valori specifici per colonne specifiche.È una buona idea usare MySQL e Neo4j insieme?

Ma allo stesso tempo, memorizzerò le relazioni tra tutti gli elementi, che sono correlati in molte strutture binari ad albero collegate (chiusura transitiva), e le banche dati delle relazioni non sono adatte a quel tipo di strutture, quindi vorrebbe memorizzare tutte le relazioni in Neo4j che hanno buone prestazioni per questo tipo di dati.

Il mio piano è di avere tutti i dati tranne le relazioni nel database MySQL e tutte le relazioni con item_id memorizzate nel database Neo4j. Quando voglio di ricercare un albero, in primo luogo ho cerco la Neo4j per tutta la item_id: s nell'albero, quindi cerco il MySQL database per tutti gli elementi specificati in una query che sarà simile:

SELECT * FROM items WHERE item_id = 45 OR item_id = 345435 OR item_id = 343 OR item_id = 78 OR item_id = 4522 OR item_id = 676 OR item_id = 443 OR item_id = 4255 OR item_id = 4345

È una buona idea o mi sbaglio? Non ho mai usato i database grafici. Ci sono approcci migliori al mio problema? Come funzionerebbe la query MySQL in questo caso?

+6

Potrebbe sostituire il diverso "OR" con una clausola "IN" :) – Mik378

+1

@Jonas Cosa hai fatto. Sono interessato a sapere come hai risolto il problema? – Medorator

+0

Per i nuovi lettori di questa domanda: Nel libro [Sviluppo aziendale continuo in Java] (http://shop.oreilly.com/product/0636920025368.do) e [questo codice] (https://github.com/arquillian/continuous-enterprise-development) utilizza questa soluzione architettonica. C'è un capitolo che giustifica la scelta di mescolare i due database. – Mats

risposta

25

Pochi pensieri su questo:

vorrei provare modellare il vostro modello di dominio Neo4j per includere gli attributi di ciascun nodo del grafo. Separando i tuoi dati in due diversi archivi dati potresti limitare alcune operazioni che potresti voler fare.

Immagino che si tratti di ciò che si farà con il grafico? Se, ad esempio, si desidera trovare tutti i nodi connessi a un nodo specifico, i cui attributi (ad es. Nome, età, ecc.) Sono determinati valori, dovresti prima trovare l'ID nodo corretto nel tuo database MySQL e poi andare in Neo4j. Questo sembra lento ed eccessivamente complicato quando si può fare tutto questo in Neo4j. Quindi la domanda è: avrai bisogno degli attributi di un nodo quando attraversi il grafico?

I dati cambiano o sono statici? Avendo due distinti archivi di dati complicherà le cose.

Mentre generare statistiche utilizzando un database MySQL potrebbe essere più semplice di fare tutto in Neo4j, il codice richiesto per attraversare un grafico per trovare tutti i nodi che soddisfano un criterio definito non è eccessivamente difficile. Quali sono queste statistiche dovrebbero guidare la tua soluzione.

Non posso commentare le prestazioni della query MySQL per selezionare gli id ​​dei nodi. Immagino che ciò dipenda dal numero di nodi che dovrai selezionare e dalla tua strategia di indicizzazione. Sono d'accordo sul lato delle prestazioni delle cose quando si tratta di attraversare un grafico però.

Questo è un buon articolo su questo: MySQL vs. Neo4j on a Large-Scale Graph Traversal e in questo caso, quando dicono grande, significano solo un milione di vertici/nodi e quattro milioni di spigoli. Quindi non era nemmeno un grafico particolarmente denso.

+0

Il pericolo con l'inclusione di più attributi è che finirai con il sandhorning di tutti i tuoi dati nel database grafico. Penso che la capacità di combinare facilmente più tipi di datastore e anche di segnalarli facilmente sia necessaria. – Eelco

+1

Perché "questo sembra solo lento"? Se recupero gli id ​​da una query neo4j e poi creo 'WHERE IN (ids)' sul relazionale, perché dovrebbe essere lento? È molto più veloce quindi attraversare un sacco di tavoli rendendo join, non è? Grazie! – Luccas

+0

@Luccas, "questo sembra solo lento ed eccessivamente complicato" perché per la maggior parte di queste query è possibile eseguirle direttamente in neo4j e non è necessario eseguire 2 query in dbs diversi, sebbene la query sql su ID (primario) dell'indice ovviamente sii veloce – vish4071

4

È possibile migliorare la query utilizzando IN:

SELECT * 
FROM items 
WHERE item_id IN (45, 345435, 343, 78, 4522, 676, 443, 4255, 4345) 

Inoltre non è del tutto vero che i database relazionali sono affatto male la memorizzazione di strutture ad albero. Certamente a MySQL mancano alcune funzionalità che lo renderebbero più semplice, ma la maggior parte degli altri database lo supportano bene. Oracle ha CONNECT BY. La maggior parte degli RDBMS mainstream ha qualche forma di query ricorsive - MySQL è un'eccezione degna di nota. Forse potresti dare un'occhiata a PostgreSQL e vedere se soddisfa le tue esigenze?

+2

Oppure usa set nidificati, che sono utili per eseguire operazioni di lettura su percorsi/sotto alberi. Comunque, qualunque approccio tu segua, mi sembra ancora molto simile a combattere lo strumento per me, mentre lavorare con database di grafi per dati appropriati sembra naturale, e ha il vantaggio aggiuntivo (teorico almeno) di ottimizzazione e visualizzazione specifiche ecc. – Eelco

5

Sono principalmente con nerd binario su questo, ma vorrei aggiungere una variazione. È possibile memorizzare i dati in tempo reale in Neo4j e quindi estrarre i dati necessari per le statistiche/i rapporti e inserirli in MySQL. Per le ricerche andrei con lo Neo4j-Lucene integration se questo si adatta alle tue esigenze.

8

I database relazionali possono gestire le strutture del grafico. Alcuni di loro possono persino gestirli in modo moderatamente elegante (con la stessa eleganza di un database relazionale!).

La chiave per la gestione generale del grafico nei database relazionali è lo recursive common table expression (RCTE), che in pratica consente di eseguire iterativamente (non in modo ricorsivo, nonostante il nome) espandere una query su un insieme di righe, combinando una query che seleziona una radice set di righe e una query che definisce i vicini delle righe selezionate finora. La sintassi è un po 'goffa, ma è generale e potente.

Gli RCTE sono supportati in PostgreSQL, Firebird, SQL Server e apparentemente in DB2. Oracle ha un costrutto diverso ma equivalente; Ho letto che le versioni recenti supportano gli RCTE appropriati. MySQL non supporta RCTE. Se non sei legato a MySQL, ti esorto a considerare l'utilizzo di PostgreSQL, che è fondamentalmente un database molto migliore a tutto tondo.

Tuttavia, sembra che non sia necessario supportare grafici generici, solo alberi. In tal caso, ci sono opzioni più specifiche a te aperte.

Uno è il classico, ma piuttosto ingannevole nested sets.

Uno più semplice è memorizzare un percorso con ogni riga: si tratta di una stringa che rappresenta la posizione della riga nell'albero e ha la proprietà che il percorso per un nodo è un prefisso del percorso per qualsiasi sottonodo, che ti consente di eseguire in modo molto efficiente varie query sull'antenato ("è il nodo A un figlio del nodo B?", "qual è il più basso antenato comune del nodo A e del nodo B?", ecc.). Ad esempio, puoi costruire un percorso per una fila camminando l'albero dalla radice e unendo gli ID delle righe incontrate sulla strada con le barre. Questo è semplice da costruire, ma si presta a mantenere se si riorganizza l'albero. Con una colonna percorso, è possibile limitare una query a un dato albero semplicemente aggiungendo and path like '23/%', dove 23 è l'ID radice.

Quindi, sebbene un database grafico sia probabilmente il modo migliore per archiviare e interrogare i dati del grafico, non è l'unica opzione e suggerirei di valutare i vantaggi dell'utilizzo di uno contro i vantaggi di avere tutti i dati in un unico database