人と場所の間に関係が存在するノードを見つけようとしているだけでなく、特定の境界ボックス内でその場所をフィルタリングしようとしています。
必要な結果を生成できますが、パフォーマンスの低下が問題になっています。
以下の例では、ユーザーから始めて、ユーザーまたはユーザーが知っているすべての場所 (最大 3 つの関係の深さ) を見つけています。
START
user = node:USER('username:"testuser"')
MATCH
user-[:KNOWS*0..3]->(users)<-[:VISITED]-place
RETURN
place;
パフォーマンスは良好です (<200 ミリ秒)。
空間フィルターを追加すると、実行時間は 10 秒に跳ね上がります。
START
user = node:USER('username:"testuser"'),
place = node:LOCATION("bbox:[-0.32487837,0.10114981,50.469185,52.508842]")
MATCH
user-[:KNOWS*0..3]->(users)<-[:VISITED]-place
RETURN
place;
空間クエリ自体は非常に迅速に (< 100 ミリ秒) 返されます。これらの開始条件の両方を組み合わせた場合にのみ、クエリにブレーキがかかります。
パフォーマンスが向上するように、このクエリを構造化するより良い方法はありますか?
空間フィルターと他のインデックス付き条件の両方を使用してクエリを実行するためのアドバイスはありますか?
追加のコンテキスト: これは Web コンソール経由の Neo4j 1.9.2 です。上記の例では、testuser からのユーザー 0 ~ 3 レベルの数は 16 です。ユニバース内の場所の数は >1000 です。境界ボックス内の場所の数は 933 です。結果の最終的な場所の数は 290 です。ノード自体は非常に小さく、ID と空間データのみです。グラフ データベース全体のサイズは約 7 MB です。
クエリ プランで更新
==> ColumnFilter(symKeys=["users", "user", " UNNAMED6", "place", " UNNAMED5"], returnItemNames=["place"], _rows=2633, _db_hits=0)
==> PatternMatch(g="(user)-[' UNNAMED5']-(users)", _rows=2633, _db_hits=0)
==> Nodes(name="user", _rows=13281, _db_hits=13281)
==> TraversalMatcher(trail="(place)-[ UNNAMED6:VISITED WHERE true AND true]->(users)", _rows=13281, _db_hits=14214)
==> ParameterPipe(_rows=1, _db_hits=0)
グラフを再構築し、メモリを調整し、実行中の他のすべてのアプリケーションをシャットダウンし、より高速なサーバーに移動して、2 秒に短縮しました。ただし、本番シナリオではデータが有効数字 2 桁増加するため、これは実際には 1/10 秒のスペースである必要があります...