neo4jバージョン3.3を実行しています。 合計650kの関係を持つ2種類のノード(合計10kノード)があります。メモリのヒープサイズは8GBです。
ノードのノードにUNIQUE CONSTRAINT
があります。ID
です。
公式neo4j-python
ドライバを使用しています(py2neo
ドライバを使用しようとしましたが、パフォーマンスはさらに悪化しました)。
次のクエリを実行すると、パフォーマンスが非常に問題になります。 1ホップ距離の場合、数分(複数のノードのリストの場合でも)かかる。 1ノードのリストを持つ2ホップ距離(以下の照会のような)については、40分以上かかる。
パフォーマンスを改善する方法はありますか?結果を処理するためneo4j cypherのパフォーマンスをリストとしてパラメータ
query = '''MATCH (n1:label1)
WHERE n1.ID IN {list}
MATCH paths=((n1)-[:relType*..2]->(n2))
WHERE n1.ID <> n2.ID AND (n2:label1 OR n2:label2)
RETURN DISTINCT paths
UNION
MATCH (n1:label2)
WHERE n1.ID IN {list}
MATCH paths=((n1)-[:relType*..2]->(n2))
WHERE n1.ID <> n2.ID AND (n2:label1 OR n2:label2)
RETURN DISTINCT paths'''
with driver.session() as session:
results = list(session.run(query, parameters={'list':list_nodes}))
if results:
df = neo4j_graph_to_df(results)
機能は以下の通りです:
def neo4j_graph_to_df(paths):
paths_dict=OrderedDict()
print(paths)
for (pathID, e) in enumerate(paths):
paths_dict[pathID]=OrderedDict()
nodes_list = [n for n in e['paths'].nodes]
rels_list = [r for r in e['paths'].relationships]
pathl = [x for x in itertools.chain.from_iterable(itertools.zip_longest(nodes_list, rels_list)) if x ]
for i, p in enumerate(pathl):
if isinstance(p, neo4j.v1.types.Node):
paths_dict[pathID]['Node'+str(i)+'Label']= str(next(iter(p.labels)))
dicti = dict(zip(['Node'+str(i)+str(np) for np in p.properties.keys()], p.properties.values()))
paths_dict[pathID] = OrderedDict({**paths_dict[pathID], **dicti})
if isinstance(p, neo4j.v1.types.Relationship):
paths_dict[pathID]['Rel'+str(i-1)]=p.type
dicti = dict(zip(['Rel'+str(i)+str(rp) for rp in p.properties.keys()], p.properties.values()))
paths_dict[pathID] =OrderedDict({**paths_dict[pathID], **dicti })
df = pd.DataFrame.from_dict(paths_dict, orient='index').fillna('0')
df = df.drop_duplicates().reset_index()
return df
Thxを。私には制約があるので、インデックスは必要ありません。 https://neo4j.com/docs/developer-manual/current/get-started/cypher/labels-constraints-and-indexes/ 1試合に変更しても、パフォーマンスは向上しませんでした。 –
こんにちは@JosephBerry!'UNION'の2つのクエリの唯一の違いは関係方向ですから、' MATCH'の方向を取り除き、 'UNION'を避けてみませんか?このようにして、次のようになります。 'MATCH paths =((n1) - [:relType * .. 2] - >(n2)) where {list} AND n1.ID <> n2.ID AND(n1:label1 OR n1:label2)AND(n2:ラベル1またはn2:ラベル2) パスを返す。それを試して助けがあれば教えてください! :) –