次の構造を持ついくつかのクライアント データに似たテスト データセットを作成しました。
*1 100k *3..30
[:author]--------> person <---------[:member]
| | |
| *2..8 |
| [:topic] |
| | |
| *3..8 V *3..8 |
article-[:topic]-> topic <-[:topic]- project
1m 1k 20k
数字は、たとえば、100 万の記事があり、それぞれに 1 人の著者がいて、各記事には 1000 のトピックのうちの 1 つに対する 3 ~ 8 の関連があります。
今、私は2つの質問があります:
最初: このレイアウトは理にかなっていますか? トピックはスーパーノードになります。ノードの属性として持つ方がよいでしょうか?
2 つ目は、クエリの表現方法によって、クエリのパフォーマンスに大きな違いがあることです。アイデアは、プロジェクトに一緒に取り組んでいて、トピックに個人的な関心を共有している人々を見つけることです:
クエリ1
match
n:person<-[:member]-p:project-[:member]->m,
n-[:topic]->t,
m-[:topic]->t
where
n.name='person1215' and
n<>m
return
m,t;
これは範囲内に戻り1500ms-9000ms
ます。
query2ははるかに高速です。
match
n:person<-[:member]-p:project-[:member]->m,
n-[:topic]->t1,
m-[:topic]->t2
where
n.name='person1250' and
n<>m and
t1=t2
return
t1,m;
に戻ります200ms-400ms
。
2 番目: なぜ query2 の方がはるかに高速なのですか? そのクエリを見るだけで、それをどのように確認できますか?
query1のプロファイラー出力:
ColumnFilter(symKeys=["n", "t", "m", " UNNAMED14", "p", " UNNAMED51", " UNNAMED35", " UNNAMED66"], returnItemNames=["m", "t"], _rows=3, _db_hits=0)
Filter(pred="((NOT(n == m) AND hasLabel(p: project)) AND hasLabel(p: project))", _rows=3, _db_hits=0)
PatternMatch(g="(p)-[' UNNAMED35']-(m),(p)-[' UNNAMED14']-(n),(m)-[' UNNAMED66']-(t),(n)-[' UNNAMED51']-(t)", _rows=3, _db_hits=0)
SchemaIndex(identifier="n", _db_hits=0, _rows=1, label="person", query="Literal(person1215)", property="name")
およびquery2の場合:
ColumnFilter(symKeys=["n", " UNNAMED67", "m", " UNNAMED14", "t2", "p", " UNNAMED51", "t1", " UNNAMED35"], returnItemNames=["t1", "m"], _rows=2, _db_hits=0)
Filter(pred="(((NOT(n == m) AND t1 == t2) AND hasLabel(p: project)) AND hasLabel(p: project))", _rows=2, _db_hits=0)
PatternMatch(g="(p)-[' UNNAMED35']-(m),(p)-[' UNNAMED14']-(n),(m)-[' UNNAMED67']-(t2),(n)-[' UNNAMED51']-(t1)", _rows=2, _db_hits=0)
SchemaIndex(identifier="n", _db_hits=0, _rows=1, label="person", query="Literal(person1250)", property="name")
どうもありがとう、
ヨルグ