2015-10-22 15 views
18

ArangoDBを使用して友人のリストを取得しようとしています。基本的な友だちリストだけでなく、ユーザーと友だちの友人数が共通していて、結果を並べ替えることができます。ArangoDBの友達友人クエリー(カウントあり)

LET friends = (
    FOR f IN GRAPH_NEIGHBORS('graph', @user, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}}) 
    RETURN f._id 
) 

LET foafs = (FOR friend IN friends 
    FOR foaf in GRAPH_NEIGHBORS('graph', friend, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}}) 
    FILTER foaf._id != @user AND foaf._id NOT IN friends 
    COLLECT foaf_result = foaf WITH COUNT INTO common_friend_count 
    RETURN { 
     user: foaf_result, 
     common_friend_count: common_friend_count 
    } 
) 
FOR foaf IN foafs 
    SORT foaf.common_friend_count DESC 
    RETURN foaf 

は残念ながら、パフォーマンスは私が言っていただろうほど良好ではない: は最高性能AQLクエリを書くことで、いくつかの試み(再)した後、これは私がしてしまったものです。同じクエリ(およびデータ)のNeo4jバージョンと比較して、AQLはかなり遅い(5-10x)ようです。

私が知りたいことは...私たちのクエリを改善してパフォーマンスを向上させるにはどうすればよいですか?

答えて

19

私はArangoDBのコア開発者の一人で、クエリを最適化しようとしました。私はあなたのdatasetを持っていないので、私は自分のテストdatasetについてしか話すことができませんし、私の結果を検証することができれば幸いです。

まず、すべて私がArangoDB 2.7を実行している場合ですが、この特定のケースでは、2.6と大きなパフォーマンスの違いはないと思います。

私のdatasetでは、約7秒でクエリを実行できました。 最初の修正: 友人の声明ではincludeData: trueを使用し、_idを返すだけです。 includeData: falseGRAPH_NEIGHBORSと直接_idを返し、我々はまた、ここに

LET friends = GRAPH_NEIGHBORS('graph', 
           @user, 
           {"direction": "any", 
           "edgeExamples": { 
            name: "FRIENDS_WITH" 
       }}) 

サブクエリを取り除くことができます。これは、私のマシン上〜1.1秒にそれをダウンしました。だから私はこれがNeo4Jのパフォーマンスに近いと思う。

これはなぜ大きな影響を与えますか? 内部的には、最初に文書JSONを実際にロードせずに_idという値が見つかりました。クエリではこのデータは必要ありませんので、安全に開くことができます。

しかし、今の本当の改善のための

あなたのクエリは、「論理的」道を行くと、最初のユーザーの隣人を取得し、彼らの隣人を見つけるよりも、foafを発見し、それをソートされた頻度をカウントします。 これはメモリ内に完全なfoafネットワークを構築し、それを全体としてソートする必要があります。

あなたはまた、別の方法でそれを行うことができます。 1.各foafについては、ユーザーのすべてのfriends(のみ_ids) 2.すべてfoaf(完全な文書)を検索 3.すべてfoaf_friends(のみ_ids) を探します4. friendsfoaf_friendsの交差点を検索し、それらを

このクエリは、この希望COUNT:

LET fids = GRAPH_NEIGHBORS("graph", 
          @user, 
          { 
          "direction":"any", 
          "edgeExamples": { 
           "name": "FRIENDS_WITH" 
           } 
          } 
         ) 
FOR foaf IN GRAPH_NEIGHBORS("graph", 
          @user, 
          { 
           "minDepth": 2, 
           "maxDepth": 2, 
           "direction": "any", 
           "includeData": true, 
           "edgeExamples": { 
           "name": "FRIENDS_WITH" 
           } 
          } 
          ) 
    LET commonIds = GRAPH_NEIGHBORS("graph", 
            foaf._id, { 
            "direction": "any", 
            "edgeExamples": { 
             "name": "FRIENDS_WITH" 
            } 
            } 
           ) 
    LET common_friend_count = LENGTH(INTERSECTION(fids, commonIds)) 
    SORT common_friend_count DESC 
    RETURN {user: foaf, common_friend_count: common_friend_count} 

私のテストグラフで〜0で実行されました。024秒

だからこれは私に率250速い実行時間を与え、私はこれはのNeo4jであなたの現在のクエリよりも高速であることを期待するが、私はあなたのdataset私はそれを確認することはできませんていないので、それは次のようになりあなたがそれをして、私に教えてくれればよい。 edgeExamples: {name : "FRIENDS_WITH" } it is the same as with includeData`で

最後に一つ

、このケースでは、私たちは本当のエッジを見つけ、それを検討する必要があります。これは、名前に基づいて別のコレクションにエッジを保存すると回避できます。また、edgeExamplesも削除します。これによりパフォーマンスがさらに向上します(特にエッジが多い場合)。私たちの次のリリースに合わせて調整

今後

滞在は、我々は今照会する方がはるかに簡単にあなたのケースを行いますし、別のパフォーマンスの向上を与える必要がありますAQLにいくつかのより多くの機能を追加しています。

+0

ありがとうございます!私はあなたの答えを確認し、確認し、受け入れるでしょう。 ) –

+1

私たちの場合、あなたの最初の改善は私たちのバージョンよりもはるかに速かったです。特に、最も遅いクエリは改善のメリットがあります。それは確かにNeo4jバージョンに非常に近いAQL結果をもたらしました。 2番目のクエリに関しては、最悪の場合のfoafクエリを高速化しましたが、最良のクエリは少し遅くなりました。(いずれにせよ、最初の改善が私たちを多く助けました)。 –

関連する問題