2013-10-21 6 views
7

Meine Chiffre Abfrage lautet wie folgt (Suche Benutzer, um herauszufinden, die in Sektoren gekauft haben)Hierarchische Stil Abfrage hat erschreckende Leistung in Cypher .. Sollte ich Traverser API verwenden?

START n=node:sectors('SECTOR_ID:65, SECTOR_ID:66 ...') // 20 sectors 
MATCH (n)-[:HAS_DOMAIN]->(dom)-[:HAS_CAT]->(cat)<-[:BELONGS_TO]-(prod)-[:BOUGHT_BY]->(user) 
RETURN n.sector_name, COUNT(user), COLLECT(DISTINCT(product.name)), ... etc. 

Ich finde, dass da bei jeder Überquerung der Anzahl von Pfaden exponentiell ansteigt, die letzte Anfrage ein Ergebnis hat Zeit von 25 Sekunden. Also, d. H. Wenn ein Sektor 50 Domänen hat, hat jede Domäne 1000 Kategorien und jede Kategorie hat 250K ++ - Produkte.

Es scheint mir das ist das 'Supernode Problem' ... oder es gibt einfach zu viele Wege!

Soll ich die Traverser-API verwenden? Sollte ich versuchen, meine Daten anders zu modellieren?

Irgendwelche Ideen willkommen!

Neo4j 1.8.3, Linux

Dank!

+0

Macht es einen Unterschied, wenn Sie die Abfrage mit 'WITH' in zwei teilen? Ich glaube nicht, dass ich jemals mit solch einem offenen Muster hinterfragt habe, aber mein Sinn wäre es, den Speicherverbrauch zu profilieren und mit der gleichen Suchanfrage zu vergleichen, etwas wie "...-> (cat) WITH CAT MATCH. .. ", wie ich es erwarten würde, dass es komplett mit der ersten Hälfte des Musters übereinstimmt, bevor es mit dem Rest weitergeht. Fuzzy-Verdacht-Vorbehalt. – jjaderberg

+0

Es könnte eine Reihe von Dingen hier los sein - Erstens, Sie tun eine Tonne von Nachschlagen auf Sektoren - jeder von ihnen könnte ~ 1 Sek. Dauern. Haben Sie versucht, von den Benutzern zurück zu suchen? Alle Benutzer, die etwas gekauft haben und basierend auf den bestehenden Beziehungen zurück zu den Sektoren navigieren? –

+0

@Mike Nein, die Suche dauert nur ein paar Millis (durch Lucene). Die Kosten beginnen groß zu werden, wenn sich die Pfade multiplizieren. Nein, ich kann nicht von den Benutzern starten, ich möchte aggregierte Statistiken über Benutzer pro Sektor erhalten. – Nikos

Antwort

0

Ihr Hauptproblem ist tatsächlich Speicher, wie Sie versuchen, alle Pfade zu laden. Wenn es sich um Statistiken handelt, die Sie wünschen, werden Sie mit der Traverser-API wahrscheinlich besser bedient, so dass Sie steuern können, wie Knoten geladen/aggregiert werden.

Wenn Sie bei Cypher bleiben möchten, kann es hilfreich sein, jeden Sektor in seine eigene Abfrage zu zerlegen, damit sie besser parallel ausgeführt werden können. Wenn Sie die vollständige Kontrolle über das Lesen/Schreiben der Datenbank haben, dann haben Sie die Möglichkeit, Sachkonten zu erstellen, die Sie beim Lesen/Schreiben aktualisieren können. Auf diese Weise müssen Sie nicht alle Pfade kennen, sondern nur, wie sich diese eine Änderung auf die Statistik auswirkt. Sie können auch direkte Beziehungen von Sektor zu interessanten Knoten erstellen und sammeln nur die Informationen, die Sie in einem einzigen Element wollen wie

(sector)-[:HAS_CAT]->(cat) 
WITH sector, collect(cat.name) as Categories 

auf diese Weise, mit jedem Spiel können Sie Ihre ursprüngliche Anzahl der Spalten konsolidieren zurück.