4

私のセットアップ:

Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
Neo4j 2.0.0-M06 Enterprise

最初に、次を実行してキャッシュをウォームアップしたことを確認しました。

START n=node(*) RETURN COUNT(n);
START r=relationship(*) RETURN count(r);

テーブルのサイズは 63,677 ノードと 7,169,995 リレーションシップです

今、私は次のクエリを持っています:

START u1=node:node_auto_index('uid:39')
MATCH (u1:user)-[w:WANTS]->(c:card)<-[h:HAS]-(u2:user)
WHERE u2.uid <> 39
WITH u2.uid AS uid, (CASE WHEN w.qty < h.qty THEN w.qty ELSE h.qty END) AS have
RETURN uid, SUM(have) AS total
ORDER BY total DESC
SKIP 0
LIMIT 25

この UID には、ページネーションを追加できるようにしたい約 40,000 件以上の結果があります。最初のスキップは約773msでした。ページ 2 (スキップ 25) を試してみましたが、レイテンシは 500 ページまではほぼ同じで、上昇しただけ900msなので、あまり気にしませんでした。ここで、早送りページングを試してみて、数千単位でジャンプしたので、1000、次に 2000、次に 3000 を実行SKIPしました。それぞれをもう一度繰り返します。しかし、1000 スキップするごとに、レイテンシーが大幅に増加しました。1つはすでにキャッシュをウォームアップしており、2つはスキップごとに同じスキップを数回試したところ、同じ結果が得られたため、単なるキャッシュウォーミングではありません。

SKIP    0:  773ms
SKIP 1000: 1369ms
SKIP 2000: 2491ms
SKIP 3000: 3899ms
SKIP 4000: 5686ms
SKIP 5000: 7424ms

一体誰が 5000 ページの結果を見たいと思うでしょうか? 40kも?!:) いい視点ね!おそらく、ユーザーが表示できる最大の結果に上限を設ける予定ですが、私はこの現象に興味がありました. なぜNeo4jがすでに知っているように見えるものを繰り返しているように見えるのか、誰か説明してくれませんか?

0スキップの私のプロファイリングは次のとおりです。

==> ColumnFilter(symKeys=["uid", "  INTERNAL_AGGREGATE65c4d6a2-1930-4f32-8fd9-5e4399ce6f14"], returnItemNames=["uid", "total"], _rows=25, _db_hits=0)
==> Slice(skip="Literal(0)", _rows=25, _db_hits=0)
==>   Top(orderBy=["SortItem(Cached(  INTERNAL_AGGREGATE65c4d6a2-1930-4f32-8fd9-5e4399ce6f14 of type Any),false)"], limit="Add(Literal(0),Literal(25))", _rows=25, _db_hits=0)
==>     EagerAggregation(keys=["uid"], aggregates=["(  INTERNAL_AGGREGATE65c4d6a2-1930-4f32-8fd9-5e4399ce6f14,Sum(have))"], _rows=41659, _db_hits=0)
==>       ColumnFilter(symKeys=["have", "u1", "uid", "c", "h", "w", "u2"], returnItemNames=["uid", "have"], _rows=146826, _db_hits=0)
==>         Extract(symKeys=["u1", "c", "h", "w", "u2"], exprKeys=["uid", "have"], _rows=146826, _db_hits=587304)
==>           Filter(pred="((NOT(Product(u2,uid(0),true) == Literal(39)) AND hasLabel(u1:user(0))) AND hasLabel(u2:user(0)))", _rows=146826, _db_hits=146826)
==>             TraversalMatcher(trail="(u1)-[w:WANTS WHERE (hasLabel(NodeIdentifier():card(1)) AND hasLabel(NodeIdentifier():card(1))) AND true]->(c)<-[h:HAS WHERE (NOT(Product(NodeIdentifier(),uid(0),true) == Literal(39)) AND hasLabel(NodeIdentifier():user(0))) AND true]-(u2)", _rows=146826, _db_hits=293696)

5000 スキップの場合:

==> ColumnFilter(symKeys=["uid", "  INTERNAL_AGGREGATE99329ea5-03cd-4d53-a6bc-3ad554b47872"], returnItemNames=["uid", "total"], _rows=25, _db_hits=0)
==> Slice(skip="Literal(5000)", _rows=25, _db_hits=0)
==>   Top(orderBy=["SortItem(Cached(  INTERNAL_AGGREGATE99329ea5-03cd-4d53-a6bc-3ad554b47872 of type Any),false)"], limit="Add(Literal(5000),Literal(25))", _rows=5025, _db_hits=0)
==>     EagerAggregation(keys=["uid"], aggregates=["(  INTERNAL_AGGREGATE99329ea5-03cd-4d53-a6bc-3ad554b47872,Sum(have))"], _rows=41659, _db_hits=0)
==>       ColumnFilter(symKeys=["have", "u1", "uid", "c", "h", "w", "u2"], returnItemNames=["uid", "have"], _rows=146826, _db_hits=0)
==>         Extract(symKeys=["u1", "c", "h", "w", "u2"], exprKeys=["uid", "have"], _rows=146826, _db_hits=587304)
==>           Filter(pred="((NOT(Product(u2,uid(0),true) == Literal(39)) AND hasLabel(u1:user(0))) AND hasLabel(u2:user(0)))", _rows=146826, _db_hits=146826)
==>             TraversalMatcher(trail="(u1)-[w:WANTS WHERE (hasLabel(NodeIdentifier():card(1)) AND hasLabel(NodeIdentifier():card(1))) AND true]->(c)<-[h:HAS WHERE (NOT(Product(NodeIdentifier(),uid(0),true) == Literal(39)) AND hasLabel(NodeIdentifier():user(0))) AND true]-(u2)", _rows=146826, _db_hits=293696)

唯一の違いは、Top 関数の LIMIT 句です。これが意図したとおりに機能することを願っています。組み込みの Neo4j と Web アプリ用の独自の Jetty REST API を深く掘り下げたくはありません。

4

1 に答える 1

2

結果はキャッシュされません。そうしないと、サーバー内の大量のメモリが、使用されない可能性が非常に高い結果を保持することになります。

そして、あなたが正しく述べているように、人々は主に最初または最初の 2 ページに興味を持ち、検索を絞り込みます。

より予測可能なページング パフォーマンスが必要な場合は、最初に neo からより多くの結果を取得し、それらをユーザー セッションに貼り付けて、そこから提供します。データベースよりもはるかに多くのコンテキスト情報を使用してこれを行うことができます (たとえば、ユーザーの行動プロファイルやパワーユーザー フラグなど)。

于 2013-10-25T23:59:01.593 に答える