Ленивая загрузка (lazy loading) - это стратегия загрузки данных, при которой связанные объекты или коллекции объектов не загружаются сразу при получении основного объекта из базы данных. Вместо этого данные загружаются только в момент фактического доступа к ним в коде приложения. В ORM это часто проявляется в отложенной загрузке связанных полей или отношений.

Ленивая загрузка, часто является источником проблемы N + 1. Когда связанные данные загружаются лениво и не предварительно, каждый доступ к ним приводит к новому запросу к базе данных, что может стать серьезной проблемой при обработке множества объектов. Например, цикл по основным объектам может привести к выполнению N дополнительных запросов (где N - количество основных объектов), что существенно увеличит количество запросов и снизит производительность.

Например, предположим, у вас есть модель Author, которая связана с моделью Book через отношение “один ко многим” (то есть каждый автор может иметь несколько книг). Если вы загрузите всех авторов и затем попытаетесь получить список всех книг каждого автора, используя цикл, это может привести к N + 1 проблеме. В этом случае, для каждого автора будет выполнен отдельный запрос к базе данных для получения списка его книг, что может привести к избыточному количеству запросов и снижению производительности.

Пример кода:

authors = Author.objects.all()
 
for author in authors:
    books = author.book_set.all()  # Для каждого автора выполняется отдельный запрос
    for book in books:
        print(book.title)
 

Для решения проблемы N + 1 часто используют методы жадной загрузки, которые позволяют выполнить только один запрос к базе данных для загрузки всех необходимых связанных данных. В Django методы **select_related()**и prefetch_related() предоставляют возможность жадной загрузки.

  • select_related(): Этот метод выполняет JOIN в базе данных и извлекает данные из связанных объектов за один запрос. Это эффективно, когда у вас есть отношение “один к одному” или “многие к одному”.

    authors = Author.objects.select_related('publisher').all()
  • prefetch_related(): Этот метод выполняет дополнительные запросы для извлечения данных из связанных объектов, но делает это в эффективной манере. Он подходит для отношений “многие ко многим”.

    authors = Author.objects.prefetch_related('books').all()

Используя жадную загрузку, вы минимизируете количество запросов к базе данных и повышаете производительность вашего приложения, предотвращая проблему N + 1.

〰〰〰 𓆝 𓆟 𓆞 𓆝 𓆟 𓆝 𓆟 𓆞 〰〰〰