Стратегия выборки из гибернации - когда использовать “присоединиться", а когда “выбрать”?
Вопрос
Большинство ассоциаций гибернации поддерживают параметр "выборка":
fetch="join|select"
при этом "выбрать" является значением по умолчанию.
Как решить, какой из них использовать для какой ассоциации?
Я попытался изменить все с "выбрать" на "присоединиться" к приложению в целом - количество сгенерированных запросов уменьшилось, вероятно, в 10 раз, но производительность осталась точно такой же (даже стала немного хуже).
Спасибо.
Решение
Соединение должно решить проблему n+1.Если у вас 10 родителей, у каждого по 10 детей, для соединения потребуется один запрос, а для выбора — 11 (по одному для родителей и по одному для детей каждого родителя).Это может не иметь большого значения, если база данных находится на том же сервере, что и приложение, или если сеть очень быстрая, но если при каждом вызове базы данных есть задержка, она может увеличиться.Метод соединения немного менее эффективен при выполнении первоначального запроса, поскольку вы дублируете родительские столбцы в каждой строке, но совершаете только один обратный путь к базе данных.
Обычно, если я знаю, что мне понадобятся дети всех родителей, я выбираю join.Если мне понадобятся дети только нескольких родителей, я использую select.
Другие советы
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)
Относительно того, когда использовать одно поверх другого...Не совсем уверен.Вероятно, это зависит от системы баз данных.Если бы одно всегда было лучше другого, я сомневаюсь, что они потрудились бы предоставить вам такой выбор!Если вы видите одинаковую производительность для каждого из них, я бы не стал беспокоиться об этом.
Если у родителя много дочерних элементов, а у этих дочерних элементов, в свою очередь, много других, то в этом случае первоначальное «соединение» может задушить сеть.Я предлагаю в этом случае использовать «select», чтобы разделить выборки.
выборка="присоединиться"Если вы выполните fetching="join", он получит всю информацию в одном операторе выбора.
выборка="выбрать"если вы хотите использовать второй оператор выбора для извлечения связанной коллекции, то в этом случае вы будете использовать fetch="select".
источник :Стратегии загрузки в спящий режим
JOIN обычно предпочтительнее из соображений производительности.
Единственная причина использовать SELECT — это разбивка результатов по страницам (установка смещения и предела), которые имеют отношение «многие ко многим».Если вы используете JOIN, корневой объект появится несколько раз, если он содержит несколько дочерних объектов типа «многие-ко-многим», и эти «копии» засчитываются в ваш лимит (даже если Hibernate сворачивает их постфактум с помощью DISTINCT_ROOT_ENTITY).
Люди всегда говорят о снижении производительности, используя выборка = ПРИСОЕДИНЯЙТЕСЬ.Но, как я считаю, нам важно понимать, сколько родительских/дочерних записей мы извлекаем:
Если вы хотите получить только одну родительскую запись и ожидаете, что у нее не так много дочерних записей, я бы предложил вам использовать выборка = ВЫБРАТЬ.
Если вы хотите получить все родительские записи, включая дочерние, лучше использовать выборка = ПРИСОЕДИНЯЙТЕСЬ
Просто хочу добавить примечание, что если записи лениво извлекают дочерние элементы(ленивый = правда), тогда не будет смысла использовать выборка = ПРИСОЕДИНЯЙТЕСЬ поскольку все родительские и дочерние записи загружаются за один раз.