2015-02-10 10 views
6

Sto usando neo4j 2.1.7 Recentemente stavo sperimentando le quiz Match, cercando nodi con diverse etichette. E ho scoperto, che in genere tua ricercaIl tempo di ricerca degli effetti dell'ordine delle etichette?

Match (p:A:B) return count(p) as number 

e

Match (p:B:A) return count(p) as number 

lavora a tempo diverso, estremamente nei casi in cui si dispone, ad esempio 2 milioni di nodi A e 0 di nodi B. in modo da fare le etichette effetti dell'ordine tempo di ricerca? Questo futuro è documentato ovunque?

risposta

9

Neo4j mantiene internamente un negozio di etichette - è fondamentalmente una ricerca per ottenere rapidamente tutti i nodi che trasportano un'etichetta definita A.

Quando si effettua una query come

MATCH (n:A:B) return count(n) 

labelscanstore viene utilizzato per trovare tutti A nodi e poi sono filtrati se quei nodi portano l'etichetta B pure. Se n(A) >> n(B) è il modo più efficace per fare MATCH (n:B:A) invece da quando si guarda solo pochi B nodi e filtrare quelli per A.

È possibile utilizzare PROFILE MATCH (n:A:B) return count(n) per vedere il piano di query. Per Neo4j < = 2.1.x vedrai un piano di query diverso a seconda dell'ordine delle etichette che hai specificato.

A partire da Neo4j 2.2 (pietra miliare M03 disponibile durante la stesura di questa risposta) è disponibile un ottimizzatore Cypher basato sui costi. Ora Cypher è a conoscenza delle statistiche del nodo e vengono utilizzate per ottimizzare la query.

Come esempio ho usato le seguenti istruzioni per creare alcuni dati di test:

create (:A:B); 
with 1 as a foreach (x in range(0,1000000) | create (:A)); 
with 1 as a foreach (x in range(0,100) | create (:B)); 

abbiamo ora 100 B nodi, i nodi A e 1M 1 nodo AB. In 2.2 le due affermazioni:

MATCH (n:B:A) return count(n) 
MATCH (n:A:B) return count(n) 

risultato nella stessa identica piano di query (e quindi nella stessa velocità di esecuzione):

+------------------+---------------+------+--------+-------------+---------------+ 
|   Operator | EstimatedRows | Rows | DbHits | Identifiers |   Other | 
+------------------+---------------+------+--------+-------------+---------------+ 
| EagerAggregation |    3 | 1 |  0 | count(n) |      | 
|   Filter |   12 | 1 |  12 |   n | hasLabel(n:A) | 
| NodeByLabelScan |   12 | 12 |  13 |   n |   :B | 
+------------------+---------------+------+--------+-------------+---------------+ 

Poiché ci sono solo poche B nodi, è più economico per la ricerca di B e filtro per A. Smart Cypher, non è vero ;-)

+1

Ottima risposta. Con l'imminente pianificatore basato sui costi, questo cambierà? L'ottimizzatore sarà in grado di farlo in un altro modo se è più veloce? – FrobberOfBits

+1

Lo fa in realtà in 2.2.0-M03 - lo ha appena controllato. –

+0

In 2.2.10 l'ordine delle etichette è ancora valido per le query cifrate. Il mio test locale ha prodotto quantità diverse di hit db: 27509335! = 111913 – manonthemat