2015-10-26 20 views
13

Sto definendo la relazione tra due entità, Gene e Cromosoma, in quello che penso sia il modo più semplice e normale, dopo aver importato i dati da CSV:Perché neo4j avverte: "Questa query crea un prodotto cartesiano tra i modelli disconnessi"?

MATCH (g:Gene),(c:Chromosome) 
WHERE g.chromosomeID = c.chromosomeID 
CREATE (g)-[:PART_OF]->(c); 

Eppure, quando lo faccio, Neo4j (interfaccia utente del browser):

Questa query crea un prodotto cartesiano tra modelli disconnessi. Se una parte di una query contiene più schemi disconnessi, verrà creato un prodotto cartesiano tra tutte quelle parti. Ciò può produrre una grande quantità di dati e rallentare l'elaborazione della query. Anche se occasionalmente previsto, può essere spesso possibile riformulare la query che evita l'uso di questo prodotto incrociato, magari aggiungendo una relazione tra le diverse parti o utilizzando OPTIONAL MATCH (l'identificatore è: (c)).

Non vedo quale sia il problema. chromosomeID è una chiave estranea molto semplice.

+0

Puoi dare un esempio di una partita particolare e dei loro ID? Sto cercando di visualizzare le relazioni che stai creando. – jgloves

+0

Inoltre, hai altri tipi di relazioni oltre a [: PART_OF]? – jgloves

+0

Questo è solo un avvertimento, e nel tuo caso non c'è niente da fare (a causa della mancanza di relazione tra questi nodi, ed è esattamente quello che crei in questa query!). Gli avvisi nel browser neo4j sono stati aggiunti in 2.3, per informare l'utente quando probabilmente esegue una query errata (ad esempio con prestazioni non buone). – logisima

risposta

20

Il browser vi sta dicendo che:

  1. Si sta gestendo la query facendo un confronto tra tutti i Gene istanza e ogni Chromosome esempio. Se il DB ha geni G e cromosomi C, la complessità della query è O(GC). Per esempio, se stiamo lavorando con il genoma umano, ci sono 46 cromosomi e forse 25000 geni, quindi il DB dovrebbe fare confronti 1150000.
  2. Potrebbe essere possibile migliorare la complessità (e le prestazioni) alterando la query. Ad esempio, se abbiamosu :Gene(chromosomeID) e modificato la query in modo che inizialmente corrispondessimo solo sul nodo con la cardinalità più piccola (i 46 cromosomi), faremmo solo "confronti" con O(G) (o 25000) - e tali confronti sarebbero in realtà sono indici rapidi! Questo approccio dovrebbe essere molto più veloce.

    Una volta creato l'indice, possiamo utilizzare questa query:

    MATCH (c:Chromosome) 
    WITH c 
    MATCH (g:Gene) 
    WHERE g.chromosomeID = c.chromosomeID 
    CREATE (g)-[:PART_OF]->(c); 
    

    Si utilizza una clausola WITH per forzare il primo MATCH clausola da eseguire per primo, evitando il prodotto cartesiano. La seconda clausola MATCH (e WHERE) utilizza i risultati della prima clausola MATCH e l'indice per ottenere rapidamente i geni esatti che appartengono a ciascun cromosoma.

+0

Grazie! Capisco! Ho degli indici su tutti gli ID per velocizzare le cose, sia le chiavi primarie che le chiavi esterne, e ci sono alcune grandi e grandi query di grandi dimensioni, come ProteinMatch su Polipeptide, quindi la corrispondenza in due passaggi che suggerisci sarà di grande aiuto in questi casi. –

+0

Per la cronaca, questa era la soluzione e velocizzava la query in modo massiccio. Immagino di essere rovinato dall'ottimizzazione automatica delle query in DB come PostgreSQL; sembra che bisogna essere un po 'più attenti in neo4j. –

3

Come logisima menziona nei commenti, questo è solo un avvertimento. La corrispondenza con un prodotto cartesiano è lenta. Nel tuo caso dovrebbe essere OK poiché vuoi connettere i nodi Gene e Chromosome precedentemente non connessi e conosci la dimensione del prodotto cartesiano. Non ci sono troppi cromosomi e un numero ridotto di geni. Se vuoi MATCH ad es. geni sulle proteine ​​la query potrebbe esplodere.

Penso che l'avvertimento è destinato per altre query problematici:

  • se MATCH un prodotto cartesiano, ma non si sa se v'è un rapporto che si potrebbe usare OPTIONAL MATCH
  • se si vuole MATCH sia un Gene e Chromosome senza relazioni, si dovrebbe dividere la query

Nel caso in cui la query richiede troppo tempo o non termina, qui è un'altra questione dando alcuni suggerimenti su come ottimizzare i prodotti cartesiani: How to optimize Neo4j Cypher queries with multiple node matches (Cartesian Product)