ActiveJDBC активно загружает полиморфных родителей

Я не могу загрузить полиморфный родительский класс дочернего класса. Включающее утверждение, кажется, не имеет значения.

Детский класс:

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

Родительский класс:

public class ParentRequest extends Model {

}

Запрос, который должен с нетерпением вернуть 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");
     ...
 }

Я выполнил эти операции, и описанная выше операция, кажется, занимает около 67 мс независимо от того, используется ли.include(ParentRequest.class) в методе Child.where() или нет.

Любое понимание или помощь очень ценится.

ПРИМЕЧАНИЕ: я знаю, что у ребенка только один родитель. В ближайшее время его будет несколько.

РЕДАКТИРОВАТЬ: инвертирование запроса привело к гораздо более быстрым результатам по некоторым причинам. То есть, вместо того, чтобы искать Children и включать ParentRequest, если я искал ParentRequest и включал Child, операция была намного быстрее. Обратите внимание, что я специально сделал 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

Как видите, к базе данных было только два запроса. Кроме того, строка, которую вы упоминаете:

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

не будет компилироваться, потому что LazyList не имеет члена cachedParents,

Если вы перебираете детей в этом случае, и получаете родителя как:

child.parent(Parent.class)

, к базе данных не будет запросов к базе данных, поскольку объекты кэшируются в памяти.

Каркас работает как положено. Причина, по которой ваш выбор времени одинаков с и без include() s размер вашего набора данных. 67 миллисекунд - это довольно быстро, и "узкое место" есть везде.

Чтобы увидеть разницу, вам нужно загрузить гораздо больший набор данных.

Кроме того, имейте в виду, что чем больше данных вы загружаете, тем больше пространства кучи вы будете выделять. В конечном итоге include() Метод решает проблему N+1 ( http://javalite.io/lazy_and_eager), но это не значит, что ваше приложение будет работать быстрее. Вам нужно поэкспериментировать и решить, лучше ли его использовать или нет для ваших случаев.

Резюме: если вы используете include() метод, вы будете иметь меньше обращений к базе данных, но выделите больше оперативной памяти. Вам решать, будет ли это быстрее для вашего приложения.

Другие вопросы по тегам