Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Эффективное использование ORM Python: Django ORM

Как и любое средство повышения уровня абстракции, ORM может выдавать не самые эффективные запросы в некоторых случаях. К сожалению, по-другому быть не может: тонко настроенные SQL-запросы находятся на существенно более низком уровне. В Django ORM можно переписывать код запроса руками, но есть ли в этом необходимость? Вовсе нет.

Для начала прочтем отрывок из документации к фреймворку:

  1. Сначала измерьте. У любого QuerySet можно запросить описание предполагаемых запросов с помощью вызова метода .explain(). Тут пригодится умение читать SQL и понимать то, о чем рассказывает через explain ваша СУБД
  2. Добавьте индексы. SQL explain часто может сказать, что в каком-то месте делается "full scan" то есть полный перебор, а это означает, что где-то не хватает индексов. Стоит подумать о том, чтобы оные добавить. Подробности можно почитать в документации
  3. Делайте как можно больше работы силами СУБД. Аннотируйте, агрегируйте. СУБД знает, как это оптимизировать и как кэшировать результаты.
  4. В крайнем случае пишите необходимый минимум SQL.
  5. Знайте, как работают QuerySets и помните:
  • Насколько QuerySets ленив — он не делает лишних запросов, пока вы не попросите
  • В какой момент QuerySet вычисляется (финализируется)
  • Каким образом данные представлены в памяти
  • Как QuerySet кеширует результаты запросов и подзапросов

Следует помнить, что многие ситуации разрешаются задолго до того, как вы дойдете до написания SQL.

Построитель запросов Django ORM позволяет решать многие задачи, не сильно усложняя код запросов. Разберем два класса улучшений: ограничение состава запрашиваемых данных и раннюю загрузку связанных данных.

Ограничение состава загружаемых данных

Довольно часто нам не требуются все поля модели — нужна всего пара полей из нескольких десятков. Тут пригодится метод .values_list(имена, полей), который возвращает новый QuerySet. Его элементами будут кортежи со значениями указанных полей в указанном же порядке. Такой QuerySet удобно обходить в цикле с одновременной распаковкой:

for pid, title in Post.objects.values_list('id', 'title'):
    print(pid, '|', title)

# SELECT "blog_post"."id",
#        "blog_post"."title"
#   FROM "blog_post"

# Execution time: 0.000571s [Database: default]
# => 1 | Intro
# => 2 | Update

Если значений нужно не два и не три, то есть смысл использовать метод .values(имена, полей). При обходе итогового QuerySet он даст уже не кортежи, а словари с ключами, совпадающими с именами указанных полей.

Однако ни кортежи, ни словари не дают воспользоваться методами модели, а в некоторых ситуациях это все-таки требуется. Если точно известно, какие поля понадобятся при работе с моделью и при вызове ее методов, подойдет метод .only(имена, полей): возращаемый им QuerySet выдает объекты модели, но в каждом объекте заполнены только указанные поля. Так мы можем использовать все возможности модели. Но следует помнить, что первое же обращение к полю, не указанному в вызове .only(), породит запрос. Он сработает для текущего объекта — запросит данные для этого поля и запомнит их на будущее:

ps = Post.objects.only('title')
post = ps[0]  # Первый пост, загружаются только заголовки (и id)
# SELECT "blog_post"."id",
#        "blog_post"."title"
#   FROM "blog_post"
#  LIMIT 1

# Execution time: 0.000327s [Database: default]

post.title
# => 'Intro'
post.body  # Поле потребует загрузки

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Django
10 месяцев
с нуля
Старт 5 октября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»