2

サイファー クエリの変更でパフォーマンスの問題が発生しました。与えられたのは、子ノードへの発信リレーションシップが大量にある起点ノードです。これらの子ノードにはすべてキー プロパティがあります。ここでの目標は、オリジン ノードと子ノードの間に新しいノードを作成して、同じキー プロパティ値を共有するすべての子ノードをグループ化することです。そのアイデアのプロットは、neo4j コンソールにあります: http://console.neo4j.org/?id=vinntj

spring-data-neo4j 2.2.2.RELEASE および neo4j 1.9.2 埋め込みとともにクエリを使用します。そのクエリのパラメーターはノード ID である必要があり、そのクエリの結果は変更されたルート ノードである必要があります。

クエリは現在次のようになっています (リンクされた neo4j コンソールよりも少し複雑です):

START root=node({0})
MATCH (root)-[r:LEAF]->(child)
SET root.__type__='my.GroupedRoot'
DELETE r
WITH child.`custom-GROUP` AS groupingKey, root AS origin, child AS leaf
CREATE UNIQUE (origin)-[:GROUP]->(group{__type__:'my.Group',key:'GROUP',value:groupingKey,origin:ID(origin)})-[:LEAF]->(leaf)
RETURN DISTINCT origin

プロパティ custom-GROUP は、グループ化のキーです。SDN では、DynamicProperties オブジェクトによって表されます。作成されたグループ ノードの groupingKey および origin プロパティと同様に、インデックスを作成するように注釈を付けました。

5000 の子ノードがある場合、それらをグループ化するのに約 50 秒かかります。10000 ノードの場合、約 90 秒。20000 ノードの場合は ~380 秒、30000 ノードの場合は > 50 分! これは、私には o(log n) スケールのように見えます。しかし、私の目標は o(n) スケールであり、500000 以上の子ノードを 30 分未満で処理することです。そのクエリの CREATE UNIQUE 部分がその問題を引き起こしていると思います。なぜなら、新しいグループ ノードの場合、どの種類のグループ ノードが既に作成されているかを常に確認する必要があるからです。また、チェックする量は、すでにグループ化されている子ノードの量に応じて増加します。

このクエリをより速く取得する方法について誰かが考えていますか? または、他のクエリで同じことをより速く行うには?

4

2 に答える 2

1

CREATE UNIQUE が実際に問題である場合、これは最初にグループを作成し、次にそれらにマップします。

START root=node(*)
MATCH (root)-[r:LEAF]->(child) 
WHERE HAS (root.key) AND root.key='root' 
WITH DISTINCT child.key AS groupingKey, root as origin
CREATE UNIQUE (origin)-[:GROUP]->(intermediate { key:groupingKey,origin:ID(origin)})
WITH groupingKey, origin, intermediate
MATCH (origin)-[r:LEAF]->(leaf)
WHERE leaf.key = groupingKey
DELETE r
CREATE (intermediate)-[:LEAF]->(leaf)
RETURN DISTINCT origin

コンソールでは、何らかの理由でいずれかのクエリの実行計画を表示できないため、それが役立つかどうかはわかりません。

すべてのノードで「WHERE」を実行する必要がないように、ルートにインデックスを付けることも検討してください。key=root のインデックスを確認するだけです。

EDIT上記のクエリの代替は次のとおりです。これにより、収集を使用してリーフノードを2回一致させる必要がなくなります。

START root=node(*)
MATCH (root)-[r:LEAF]->(child) 
WHERE HAS (root.key) AND root.key='root'
DELETE r 
WITH DISTINCT child.key AS groupingKey, root as origin, COLLECT(child) as children
CREATE UNIQUE (origin)-[:GROUP]->(intermediate { key:groupingKey,origin:ID(origin)})
WITH groupingKey, origin, intermediate, children
FOREACH(leaf IN children : CREATE (intermediate)-[:LEAF]->(leaf))
RETURN DISTINCT origin
于 2013-08-23T16:47:15.893 に答える