- lazyload не загружается сразу, но ожидает первого доступа.
- subqueryload и joinload загружают сразу связанную коллекцию, но с использованием другого SQL.Даже если результат одинаков для обоих режимов, может быть большая разница в производительности.
Предположим, что класс A содержит список детей по отношению к B и C:
class A:
b_list = relationship(B, lazy='joined')
c_list = relationship(C, lazy='joined')
class B:
a_id = Column(ForeignKey('a.id'))
class C:
a_id = Column(ForeignKey('a.id'))
Если вы установите b_list и c_list в качестве joinload, то будет выпущен следующий sql (или аналогичный):
SELECT ... FROM A
LEFT JOIN B ON B.a_id = A.id
LEFT JOIN C ON C.a_id = A.id
WHERE ...
Если в B и C есть 1000 элементов, 1 000 000 строк будутбудет возвращен, то sqlalchemy будет сортировать дубликаты в пространстве Python.С большими числами и большим количеством связей это может даже привести к нехватке памяти в вашей базе данных или в вашем приложении.
Подзапрос не должен иметь этой проблемы, так как все отношения загружаются отдельно.Я не совсем уверен в разнице между подзапросом и selectin, но согласно документации (https://docs.sqlalchemy.org/en/13/orm/loading_relationships.html#subquery-eager-loading), selectinload в основном является улучшенной версией subqueryload.
Для чего это стоит, в нашем проекте,мы используем следующую политику (которая на самом деле автоматизирована):
- загрузка связей между отдельными элементами с joinload.
- загрузка коллекций с помощью selectinload.