2016-06-10 21 views
3

Ich versuche immer noch zu verstehen, warum ich eine kartesische Produktwarnung für ein bestimmtes Format für eine Abfrage in Neo4j und nicht für eine andere erhalten. Dies ist, wie ich meine Datenbank einrichten:Warum erhalte ich eine Warnung "kartesisches Produkt"?

CREATE (q:Form {version: "1.0"}) 
CREATE (q:Question {text: "Sector de la empresa", active: true}) 

Ich habe dann versucht, die folgende Abfrage:

MATCH 
(f:Form {version: "1.0"}), 
(q:Question {text: "Sector de la empresa"}) 
CREATE (f)-[:asks]->(q) 
RETURN f, q 

Allerdings bekomme ich die folgende Warnung:

This query builds a cartesian product between disconnected patterns. 
If a part of a query contains multiple disconnected patterns, 
this will build a cartesian product between all those parts. 
This may produce a large amount of data and slow down query processing. 
While occasionally intended, it may often be possible to reformulate the 
query that avoids the use of this cross product, perhaps by adding a 
relationship between the different parts or by using OPTIONAL MATCH 
(identifier is: (q)) 

Wenn ich die folgenden Abfrage, gibt es mir diese Warnung nicht:

MATCH (f:Form {version: "1.0"}) 
WITH f 
(q:Question {text: "Sector de la empresa"}) 
CREATE (f)-[:asks]->(q) 
RETURN f, q 
noch 0

wenn ich diese Abfrage:

MATCH (f:Form {version: "1.0"}) 
MATCH (q:Question {text: "Sector de la empresa"}) 
CREATE (f)-[:asks]->(q) 
RETURN f, q 

ich diesen folgenden Artikel als Ressource verwendet wird, aber es hat immer noch nicht ganz meine Frage beantworten: Why does neo4j warn: "This query builds a cartesian product between disconnected patterns"?

Warum ich ein kartesisches Produkt für einige bekommen Formate einer Abfrage und nicht andere? Außerdem verstehe ich nicht ganz, was eine kartesische Produktwarnung ist.

Antwort

3

Wenn Sie auf zwei verschiedenen Etiketten ohne Beziehungen zwischen ihnen sind, erhalten Sie diese Warnung. Der Grund ist, weil wenn Sie tun:

MATCH (a:Foo), (b:Bar) 

Es ist Neo4j Aufgabe, jede mögliche Kombination dieser beiden Knoten zu finden. Also für das erste Spiel von a wird es eine Zeile für jedes Spiel von b zurückgeben, für das zweite Spiel von a wird es wieder eine Zeile für jedes Spiel von b, und so weiter. So erhalten Sie (number of Foo nodes) x (number of Bar nodes) Gesamtzeilen in Ihrem Ergebnis. Wenn Ihre Datenbank wächst, ist das wirklich schlecht für die Performance.

Ich kann sehen, dass Sie sich auf version für Form und text für Question sind Filterung, helfen das wäre so. Das kann sogar nur einen Form Knoten und einen Question Knoten ergeben. Solange Sie einen Index für die Form(version) und Question(text) haben, sollte die Abfrage ziemlich schnell sein. Neo4j kann nicht sagen (oder zumindest ist es derzeit nicht implementiert, um sagen zu können), wie viele Zeilen zurückgegeben werden. Daher gibt es eine Warnung, dass Ihre Abfrage möglicherweise langsam ist.

0

Sie alle

Nachdem Sie Ihre Frage zu lesen, für eine zweite dort kartesisch sind, meine Chiffre-Welt implodiert - alle drei Abfragen ein kartesisches Produkt beinhalten sollte.

geprüft (bezogen auf sowohl the console und einem lokalen DB - sowohl Version 3.3.0), stellt sich heraus, ich bin gesund - sie alle beinhalten ein kartesisches Produkt:

The execution plan of the first query, showing a cartesian product

The execution plan of the second query, showing a cartesian product

The execution plan of the third query, showing a cartesian product

Warum gibt es im ersten Fall nur eine Warnung (noch in Version 3.3.0 Ich habe keine Ahnung - Sie müssen einfach den Planer ausführen, um dies herauszufinden, und wenn dies nicht die Warnung auslöst, was tut? Irgendeine dumme Chiffrierlogik?

Cypher Grundlagen

Cypher Abfragen von Teilen vorgenommen werden, können jeweils entweder Update (schreiben) oder gelesen werden.

Soweit Lese Teile betroffen sind, ist es das, was passiert:

  • Neo4j nimmt ein starting point die sie rechnet damit, wird die ‚Treffer‘ am wenigsten ergeben. Es wird durch jeden dieser Treffer gehen ...
  • ... durchläuft das Diagramm mit dem Knoten/Beziehung Muster.
  • Es wiederholt so oft, bis keine Muster mehr übereinstimmen.

Wenn Sie etwas wie folgt aus:

(a {name:'Bill'})-->(b:Dog) 

Der Plan so etwas wie dies aussehen könnte.

  • Für jeden Knoten (AKA AllNodeScan):
    • Filter basierend auf dem Prädikat (name == 'bill')
    • alle abgehenden --> Beziehungen Get
    • Für jede Beziehung:
      • zum Ende erhalten Knoten
      • Filter basierend auf Prädikat (:Dog)

Das Wichtigste ist, dass während (a) finden wir jeden Knoten scannen müssen. Aber wir durchqueren einfach den Graphen, um die s - Nr. AllNodeScan für letzteres zu finden.

(Es gibt Varianten von AllNodeScan finden Starting Node Operators)

Wenn Ihre Abfrage so etwas wie diese:

MATCH (f:Form {version: "1.0"}), (q:Question {text: "Sector de la empresa"}) 

Neo gezwungen ist, ein AllNodeScan sowohl für f und q zu tun - Es gibt kein Muster zwischen ihnen zu reisen. Dies kann möglicherweise eine Ergebnismenge einer f * q-Größe erzeugen, die sehr groß sein kann.

Verwandte Themen