2016-08-23 21 views
0

子クラスのポリモーフィックな親を読み込めません。インクルードステートメントは違いがないようです。多相親のActiveJDBC eager loading

子供クラス:

@BelongsToPolymorphic(
    parents = {ParentRequest.class}, 
    typeLabels = {"parent_request"}) 
public class Child extends Model { 
} 

親クラス:熱心に子供+親を返す必要があります

public class ParentRequest extends Model { 

} 

問合せ:

List<Child> children = Child.where("... limit 500").include(ParentRequest.class); 

children.size(); //this gives me 500 
children.cachedParents.size(); //this gives me 0; 

最終的に、私は次のことをスピードアップしようとしています操作:

for (Child child : children) { 
    ParentRequest pr = child.parent(); 
    // lots of pr.getString("parent_field"); 
    ... 
} 

私はこれらの操作を抑制しており、上記の操作は.include(ParentRequest.class)がChild.where()メソッドで使用されているかどうかに関係なく約67ミリ秒かかると思われます。

洞察または助けがあれば幸いです。

注:子供には親が1人しかいないことを認識しています。近い将来、いくつかのことがあります。

編集: 何らかの理由で、クエリを反転すると、はるかに高速な結果が得られました。つまり、ParentRequestを検索してChildを検索した場合、子を探してParentRequestを含めずに、操作がはるかに高速でした。私はfindBySqlを使って、結果内のparent_requestテーブルに子テーブルを結合しました。以下では、クエリの詳細について説明しました。

List<ParentRequest> parents = ParentRequest.findBySQL("SELECT child.*, parent_requests.* " + 
       "FROM child JOIN parent_requests ON child.parent_id=parent_requests.id WHERE " + 
       "RAND()<=? AND (child.metersToA BETWEEN ? AND ?) " + 
         " AND (child.metersToB BETWEEN ? AND ?) limit ?", 
       decimation_value, 
       minDistanceToA, maxDistanceToA , 
       minDistanceToB, maxDistanceToB, 
       MAX_POINTS).include(Child.class); 

答えて

1

私は簡単なテストと有効伐採書いた:コンソールに以下を記録します。このコードの

Article article = Article.findById(1); 
article.add(Comment.create("author", "tjefferson", "content", "comment 1")); 
article.add(Comment.create("author", "tjefferson", "content", "comment 2")); 
LazyList<Comment> comments = Comment.where("author = ?", "tjefferson").include(Article.class); 

System.out.println(comments.size());// does loading of data, prints 2 
Article parent1 = comments.get(0).parent(Article.class); // does not generate DB query 
Article parent2 = comments.get(1).parent(Article.class); // does not generate DB query 

assert (parent1 == parent2); // true 

実行される:

SELECT * FROM comments WHERE author = ?", with parameters: <tjefferson>, took: 1 milliseconds 
SELECT * FROM articles WHERE id IN (?)", with parameters: <1>, took: 1 milliseconds 

あなたが見ることができるようにデータベースへのクエリは2つしかありませんでした。 また、あなたが言及ライン:LazyListがメンバーcachedParentsを持っていないため

children.cachedParents.size(); //this gives me 0; 

は、コンパイルされません。

ます。この場合、子供をループ、およびget親が好きなら:オブジェクトがメモリにキャッシュされるため

child.parent(Parent.class) 

、データベースへのデータベースクエリはありません。

フレームワークは期待通りに動作しています。 include()の有無にかかわらずタイミングが同じ理由は、データセットのサイズです。 67ミリ秒はかなり速く、 "ボトルネック"はelswhereです。

あなたが必要とするのは、はるかに大きなデータセットを読み込むことです。

さらに、ロードするデータが増えるほど、割り当てられるヒープスペースが増えることに注意してください。最終的にinclude()メソッドはN + 1問題(http://javalite.io/lazy_and_eager)を解決しますが、アプリケーションが高速になるわけではありません。実験する必要があり、使用するのが最善かどうかを判断する必要があります。

要約: include()メソッドを使用すると、データベースへの呼び出しは少なくなりますが、RAMをさらに割り当てることになります。アプリの方が速いかどうかはあなた次第です。

+0

お返事ありがとうございました!メンバーのchildren.cachedParents.sizeはデバッガで見ることができるものなので、なぜ私はそれを持っているのか説明しません。何らかの理由で、私が検索を逆転させると、それは2つのテーブルを結合するクエリを実行し、インクルード(Child.class)でParentRequestを引き出すと、パフォーマンスが大幅に向上することがわかりました。上記の方法を照会すると、500ポイントを返すのに25-35秒かかりました。私がこのコメントで言及する方法を照会することで、12-15秒以内に500ポイントを返すことができました。私は下に私のpsudocodeを投稿します。 –

+0

フレームワークが期待どおりに機能していることを嬉しく思っています(100回のうち99回がそうだと確信しています)。私は何が違うのだろうと思っています。 –

+0

ロギングを有効にする:http://javalite.io/logging。あなたのケースでどのようなクエリが生成されるかを確認してください。その後、DBコンソールでこれらを手で実行し、説明を実行して、いくつかの理由が速い理由と他の原因が遅い原因を特定できます。 ActiveJDBCは単なるツールです - それはあなたにオプションを提供します:) – ipolevoy

関連する問題