2015-10-22 24 views
18

Arkadaşların-arkadaşlarının listesine ulaşmak için ArangoDB kullanmaya çalışıyorum. Sadece basit bir arkadaş-arkadaş listesi değil, aynı zamanda kaç arkadaşın ve arkadaşın arkadaşının ortak olduğunu ve sonucu nasıl sıraladığını bilmek istiyorum.En hızlı ArangoDB arkadaşlık-arkadaşları sorgu (sayısı ile)

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 

Maalesef performans ı kaldığını kadar iyi değildir: en iyi performans AQL sorgusu yazma birkaç denemeden (yeniden) sonra bu ben ile sona erdi budur. Aynı sorgu (ve veri) Neo4j sürümleri ile karşılaştırıldığında, AQL oldukça yavaş (5-10x) gibi görünüyor.

Bilmek istediğim, daha iyi performans göstermesi için sorgumuzu nasıl geliştirebilirim?

cevap

19

ArangoDB'un temel geliştiricilerinden biriyim ve sorgunuzu optimize etmeye çalışıyorum. dataset numaralı telefona sahip olmadığımdan, sadece dataset testim hakkında konuşabilirim ve sonuçlarımı doğrulayabiliyor olmanızdan memnun olurum.

Öncelikle ArangoDB 2.7 üzerinde çalışıyorum ancak bu özel durumda 2.6 için büyük bir performans farkı beklemiyorum.

Benim dataset içinde Sorgunuzu 7sec'de olduğu gibi çalıştırabilirim. İlk düzeltme: Arkadaşınızın deyimiyle includeData: true kullan ve _id'u döndür. includeData: falseGRAPH_NEIGHBORS ile doğrudan _id döner ve biz de burada

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

alt sorgu kurtulabilirsiniz Bu benim makinede ~ 1.1 sn aşağı aldık. Bu yüzden bunun Neo4J'nin performansına yakın olacağını umuyorum.

Bu neden yüksek bir etkiye sahip? Dahili olarak, ilk önce JSON belgelerini yüklemeden önce _id değerini buluyoruz. Sorgunuzda bu verilere ihtiyacınız yok, bu yüzden açmamakla güvenle devam edebiliriz.

Ama şimdi gerçek iyileşme

Sorgunuzda komşularını bulur daha, kullanıcılar komşuları alır, bir foaf bulunursa ne sıklıkta sayar ve bunları sıralar ilk "mantıklı" bir şekilde gider ve için. Bu, tüm foaf ağını bellekte oluşturmalı ve bir bütün olarak sınıflandırmalıdır.

Ayrıca farklı bir şekilde yapabiliriz

: 1. Her foaf için 3. Tüm foaf_friends (sadece _ids) bulmak kullanıcıya (sadece _ids) 2. Tüm foaf (komple belge) bulun tüm friends bul 4. friends ve foaf_friends kesişimi bulun ve onları

Bu sorgu bu istiyoruz 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} 

Test grafiğimde ~ 0'da yürütüldü.024 sn

Yani bu bana 250 daha hızlı yürütme zamanı bir faktörü verdi ve ben bu Neo4j içinde geçerli sorguyu daha hızlı olmasını beklediğiniz, ama senin dataset ben bunu doğrulamak olamaz yok gibi, olurdu eğer yapabilirsen ve söyle bana. Gerçek kenar bulup içine bakmak zorunda bu durumda

Son bir şey edgeExamples: {name : "FRIENDS_WITH" } it is the same as with includeData` ile

. Kenarlarınızı kendi adlarına göre ayrı koleksiyonlarda saklarsanız bu önlenebilir. Ve sonra edgeExamples'ları da kaldırın. Bu, performansı daha da artıracaktır (özellikle çok fazla kenar varsa). Bir sonraki sürüm için ayarlanmış

Gelecek

kal, şu anda sorgulamak için çok daha kolay savunacağım ve başka performans artışı vermelidir AQL'de biraz daha işlevsellik ekliyoruz.

+0

Teşekkürler! Cevabınızı Pazartesi günü kontrol edip onaylayacağım! Sorumuza cevap vermek için zaman ayırdığınız için çok teşekkür ederiz;) –

+1

Bizim durumumuzda, ilk geliştirmeniz bizim versiyonumuzdan önemli ölçüde daha hızlıydı. Özellikle en yavaş sorgular, geliştirmelerinizden yararlandı. Gerçekten Neo4j versiyonuna çok yakın AQL sonucunu getirdi. 2. sorguya gelince - bu bizim en kötü durumdaki felaket sorgularımızı daha hızlı yaptı, ama en iyi durum sorguları biraz daha yavaş :(. Her iki durumda da, ilk gelişme bize çok yardımcı oldu;). –