Стратегия выбора Hibernate - когда использовать "join" и когда использовать "select"?
Большинство ассоциаций Hibernate поддерживают параметр "выборки":
fetch="join|select"
с "select" значением по умолчанию.
Как решить, какой из них использовать для какой ассоциации?
Я попробовал изменить все из приложения "select" to "join" - количество сгенерированных запросов уменьшилось, вероятно, в 10 раз, но производительность осталась одинаковой (даже немного хуже).
Спасибо.
Ответы
Ответ 1
Соединение должно решить проблему n + 1. Если у вас 10 родителей, у каждого из которых 10 детей, для соединения потребуется один запрос, а для выбора потребуется 11 (один для родителей и один для детей каждого родителя). Это может быть неважно, если база данных находится на том же сервере, что и приложение, или если сеть работает очень быстро, но если в каждом вызове базы данных есть латентность, она может складываться. Метод соединения немного менее эффективен при первоначальном запросе, потому что вы дублируете родительские столбцы в каждой строке, но вы делаете только одно туда-обратно в базу данных.
В общем, если я знаю, что мне понадобятся дети всех родителей, я иду с ними. Если мне понадобятся только дети нескольких родителей, я использую select.
Ответ 2
Select будет извлекать дочерние элементы, вызывая для них новый запрос к базе данных. Join будет извлекать дочерние элементы, присоединяя их к родительскому запросу. Итак, почему вы видите подобную производительность, даже с уменьшением количества запросов.
Выбрать:
SELECT * FROM parent WHERE id=(whatever)
SELECT * FROM child WHERE id=(parent.child.id)
Регистрация:
SELECT *
FROM parent
LEFT OUTER JOIN child ON parent.child.id=child.id
WHERE parent.id=(whatever)
Что касается того, когда использовать один над другим... Не совсем уверен. Вероятно, это зависит от системы базы данных. Если кто-то всегда был лучше другого, я сомневаюсь, что они потрудились бы дать вам возможность! Если вы видите подобную производительность для каждого, я бы не стал беспокоиться об этом.
Ответ 3
выборка = "присоединиться к"
Если вы делаете fetchching = "join", он будет извлекать всю информацию в одном выражении select.
выборка = "выберите"
если вы хотите использовать второй оператор select для извлечения связанной коллекции, то в этом случае вы будете использовать fetch = "select".
источник: Стратегии по слиянию с гибернацией
Ответ 4
Люди всегда говорят об эффективности, используя fetch = JOIN. Но, как я считаю, для нас важно понять количество родительских/дочерних записей, которые мы извлекаем:
Если вы хотите получить только одну родительскую запись и ожидаете, что у нее мало детей, я предлагаю вам использовать fetch = SELECT.
Если вы хотите получить все родительские записи, включая его дочерние элементы, тогда лучше было бы выбрать fetch = JOIN
Просто добавьте примечание о том, что если записи лениво извлекают детей (lazy = true), тогда не было бы смысла использовать fetch = JOIN, поскольку все родительские и дочерние записи загружаются одним выстрелом.
Ответ 5
Если у родителя есть много детей, а у тех детей, в свою очередь, есть много других, тогда в этом случае начальное "соединение" может заглушить сеть. Мое предложение состоит в том, чтобы использовать "select" в этом случае для разделения выбранных.
Ответ 6
JOIN предпочтительнее, как правило, по соображениям производительности.
Единственной причиной использования SELECT является то, что вы выполняете поисковые запросы (устанавливаете смещение и лимит), которые имеют отношение "многие ко многим". Если вы используете JOIN, корневой объект будет появляться несколько раз, если он содержит несколько детей "много ко многим", и эти "копии" учитывают ваш лимит (даже если Hibernate обрушивает их после факта, используя DISTINCT_ROOT_ENTITY).