2015-06-19 8 views
8

Ho un grafico con un nodo che ha molte relazioni in uscita. Il tempo necessario per aggiungere nuove relazioni in uscita si riduce quando aggiungo più relazioni. Il degrado sembra essere dovuto al tempo impiegato per verificare che la relazione non sia già esistente (sto usando MERGE per aggiungere le relazioni).Come posso ottimizzare una query MERGE Neo4j su un nodo con molte relazioni?

I nodi di destinazione delle relazioni hanno pochissime relazioni. Esiste un modo per forzare Neo4j a verificare l'esistenza della relazione dal nodo di destinazione anziché dal nodo di origine?

Ecco lo script di test per riprodurre il problema. Crea un nodo con ID 0 seguito da 1000 nodi connessi al nodo 0 dalla relazione HAS. All'aggiunta dei nodi, il tempo di esecuzione aumenta in modo lineare.

CREATE CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE 

UNWIND RANGE(1,1000) AS i 
MERGE (from:Node { id: 0 }) 
MERGE (to:Node { id: i}) 
MERGE (from)-[:HAS]->to 

Aggiunto 1001 etichette, create 1001 nodi, impostare le proprietà 1001, creati 1000 relazioni, istruzione eseguita nel 3496 ms.

UNWIND RANGE(1001,2000) AS i 
MERGE (from:Node { id: 0 }) 
MERGE (to:Node { id: i}) 
MERGE (from)-[:HAS]->to 

Aggiunto 1000 etichette, creato 1000 nodi, impostare le proprietà 1000, ha creato 1000 relazioni, istruzione eseguita nel 7030 ms.

UNWIND RANGE(2001,3000) AS i 
MERGE (from:Node { id: 0 }) 
MERGE (to:Node { id: i}) 
MERGE (from)-[:HAS]->to 

Aggiunto 1000 etichette, creato 1000 nodi, impostare le proprietà 1000, ha creato 1000 relazioni, istruzione eseguita in 10489 ms.

UNWIND RANGE(3001,4000) AS i 
MERGE (from:Node { id: 0 }) 
MERGE (to:Node { id: i}) 
MERGE (from)-[:HAS]->to 

Aggiunto 1000 etichette, creato 1000 nodi, impostare le proprietà 1000, ha creato 1000 relazioni, istruzione eseguita in 14390 ms.

Se si utilizza CREATE invece di MERGE, le prestazioni sono decisamente migliori. Non posso usare CREATE perché voglio assicurarmi che le relazioni siano uniche.

UNWIND RANGE(4001,5000) AS i 
MERGE (from:Node { id: 0 }) 
MERGE (to:Node { id: i}) 
CREATE (from)-[:HAS]->to 

Aggiunto 1000 etichette, create 1000 nodi, impostare le proprietà 1000, creati 1000 relazioni, istruzione eseguita in 413 ms.

Nota: Testato con Neo4j v2.2.2

risposta

10

Questo perché cifra non è abbastanza intelligente ancora utilizzare il grado dei nodi durante l'esecuzione di merge. Nell'ottimizzatore COST che viene utilizzato per le letture è già più intelligente, ma per gli aggiornamenti viene utilizzato il vecchio ottimizzatore RULE.

Dopo aver giocato intorno con esso per un po 'senza successo * cambiando l'ordine di da & a * utilizzando CREATE UNIQUE al posto di MERGE * cercando di utilizzare path-espressioni che utilizzano get-laurea in COSTO

mi sono ricordato che shortestPath prende effettivamente conseguito in considerazione e anche va da sinistra a destra

così ho provato a combinano con CREATE, e ha funzionato molto bene, ecco un esempio per 100.000 nodi.

neo4j-sh (?)$ CREATE CONSTRAINT ON (n:Node) ASSERT n.id IS UNIQUE; 
+-------------------+ 
| No data returned. | 
+-------------------+ 
Constraints added: 1 
1054 ms 
neo4j-sh (?)$ 
neo4j-sh (?)$ UNWIND RANGE(0,100000) AS i CREATE (to:Node { id: i}); 
+-------------------+ 
| No data returned. | 
+-------------------+ 
Nodes created: 100001 
Properties set: 100001 
Labels added: 100001 
2375 ms 
neo4j-sh (?)$ 
neo4j-sh (?)$ 
neo4j-sh (?)$ MATCH (from:Node { id: 0 }) 
> UNWIND RANGE(1,100000) AS i 
> MATCH (to:Node { id: i}) 
> WHERE shortestPath((to)<-[:HAS]-(from)) IS NULL 
> CREATE (from)-[:HAS]->(to); 
+-------------------+ 
| No data returned. | 
+-------------------+ 
Relationships created: 100000 
2897 ms 
neo4j-sh (?)$ 
neo4j-sh (?)$ 
neo4j-sh (?)$ MATCH (from:Node { id: 0 }) 
> UNWIND RANGE(1,100000) AS i 
> MATCH (to:Node { id: i}) 
> WHERE shortestPath((to)<-[:HAS]-(from)) IS NULL 
> CREATE (from)-[:HAS]->(to); 
+--------------------------------------------+ 
| No data returned, and nothing was changed. | 
+--------------------------------------------+ 
2360 ms 
+0

Grazie, sembra molto promettente. Farò dei test e ti farò sapere come va. – Dave

+0

Ha funzionato? In tal caso, si prega di accettare :) –

+1

Ho provato questo e ci ha dato enormi guadagni in termini di prestazioni. In attesa di quando il pianificatore di query può effettuare automaticamente questa ottimizzazione. Grazie ancora Michael :) – Dave

Problemi correlati