ActiveJDBC 预加载多态 Parents
ActiveJDBC eager loading of Polymorphic Parents
我无法急切加载 child class 的多态 parent。 include 语句似乎没有什么区别。
Child Class:
@BelongsToPolymorphic(
parents = {ParentRequest.class},
typeLabels = {"parent_request"})
public class Child extends Model {
}
Parent Class:
public class ParentRequest extends Model {
}
急切的查询 return child + parent:
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");
...
}
我已经对这些操作进行了测试,无论是否在 Child.where() 方法上使用 .include(ParentRequest.class) ,上述操作似乎都需要大约 67 毫秒。
非常感谢任何见解或帮助。
注意:我知道 Child 只有一个 parent。近期还会有好几个。
编辑:
由于某些原因,反转查询会产生更快的结果。也就是说,如果我搜索 ParentRequest 并包含 Child,而不是查找 Children 并包含 ParentRequest,操作会快得多。请注意,我专门做了一个 findBySql 以将 child table 加入我的结果中的 parent_request table。下面我留下了查询的细节。
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);
我写了一个简单的测试,启用了日志记录:
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
如您所见,只有两次对数据库的查询。
此外,您提到的行:
children.cachedParents.size(); //this gives me 0;
不会编译,因为 LazyList
没有成员 cachedParents
。
如果在这种情况下遍历子项,并得到如下父项:
child.parent(Parent.class)
,不会有数据库查询到数据库,因为对象缓存在内存中。
该框架正在按预期工作。
在有和没有 include()
的情况下,您的时间相同的原因是数据集的大小。 67 毫秒非常快,"bottleneck" 在其他地方。
要查看差异,您需要做的是加载更大的数据集。
此外,请记住,加载的数据越多,分配的堆 space 就越多。最终 include()
方法解决了 N+1 问题 (http://javalite.io/lazy_and_eager) ,但这并不意味着你的应用程序会更快。您需要进行试验,并决定是否最好将它用于您的案例。
总结:
如果你使用 include()
方法,你对数据库的调用会更少,但会分配更多的 RAM。是否更快由您决定。
我无法急切加载 child class 的多态 parent。 include 语句似乎没有什么区别。
Child Class:
@BelongsToPolymorphic(
parents = {ParentRequest.class},
typeLabels = {"parent_request"})
public class Child extends Model {
}
Parent Class:
public class ParentRequest extends Model {
}
急切的查询 return child + parent:
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");
...
}
我已经对这些操作进行了测试,无论是否在 Child.where() 方法上使用 .include(ParentRequest.class) ,上述操作似乎都需要大约 67 毫秒。
非常感谢任何见解或帮助。
注意:我知道 Child 只有一个 parent。近期还会有好几个。
编辑: 由于某些原因,反转查询会产生更快的结果。也就是说,如果我搜索 ParentRequest 并包含 Child,而不是查找 Children 并包含 ParentRequest,操作会快得多。请注意,我专门做了一个 findBySql 以将 child table 加入我的结果中的 parent_request table。下面我留下了查询的细节。
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);
我写了一个简单的测试,启用了日志记录:
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
如您所见,只有两次对数据库的查询。 此外,您提到的行:
children.cachedParents.size(); //this gives me 0;
不会编译,因为 LazyList
没有成员 cachedParents
。
如果在这种情况下遍历子项,并得到如下父项:
child.parent(Parent.class)
,不会有数据库查询到数据库,因为对象缓存在内存中。
该框架正在按预期工作。
在有和没有 include()
的情况下,您的时间相同的原因是数据集的大小。 67 毫秒非常快,"bottleneck" 在其他地方。
要查看差异,您需要做的是加载更大的数据集。
此外,请记住,加载的数据越多,分配的堆 space 就越多。最终 include()
方法解决了 N+1 问题 (http://javalite.io/lazy_and_eager) ,但这并不意味着你的应用程序会更快。您需要进行试验,并决定是否最好将它用于您的案例。
总结:
如果你使用 include()
方法,你对数据库的调用会更少,但会分配更多的 RAM。是否更快由您决定。