Лирика
К примеру, требуется вывести в API список пользователей, но не все данные, а только их username
, и поэтому queryset=User.objects.only('username')
. Допустим, что за один запрос выводится список из 20 пользователей. Теперь мы решили добавить поля first_name
и last_name
(в сериализатор, но не в queryset). Django Rest Framework перебирает все объекты по очереди. Не обнаружив в текущем объекте поля first_name
, django делает запрос в БД за данными этого поля, потом повторяет то же самое для last_name
. И так для каждого объекта. В результате имеем один запрос к БД для получения списка объектов и ещё 20 раз по 2 запроса. Итого 41 запрос.
В данном случае достаточно добавить недостающие поля в only
или не использовать метод only
вовсе. Даже тот, кто знает о коварстве метода only
, может не знать об его участии в данном фрагменте кода. А всё потому, что подготовка queryset происходит во view, а использование в serializator.
Описанный случай, является достаточно экзотичным, но хорошо показывает, как на пустом месте вместо одного запроса можно получить множество. Гораздо чаще приходится прописывать prefetch_related
для борьбы с 1+N.
Задействуем мощь отладчика Pycharm
Если при ручном тестировании своего кода мне нужно делать обращение к API, то я всегда включаю вывод логов отладчика, чтобы видеть обращение к БД. Я покажу как это делается, но перед этим вам нужно прочитать
Прочитали? Тогда начинаем.
- Откройте свой проект django и перейдите по ссылке
CursorDebugWrapper.execute
илиCursorDebugWrapper.debug_sql
если у васDjango 3+
- Поставьте breakpoint на
logger.debug
- Сделайте правый клик на красном кружке
- В появившимся диалоге отключите
Suspend
- Включите
Evalute and log
и напишите'(%.3f) %s; args=%s'%(duration, sql, params)
Должно получится так:
Теперь, если вы запустите проект под отладчиком, то увидите в консоли все запросы к БД и время их выполнения. В моём проекте запросов в БД от вызова одного API не очень много и 1+N сразу бросается в глаза, если не включен cacheops. Отключайте cacheops на машине разработки, тогда неправильные запросы к БД вы будете буквально чувствовать на собственной шкуре без всякого логирования и не допустите плохой код в проект.
Главная прелесть логирования через отладчик в том, что не требуется вносить изменения в код, и не придётся убирать за собой забытые print'ы. При этом я не удаляю breakpoint, когда он мне не нужен, а просто выключаю (Ctrl+Shift+F8). А когда становится нужен, снова включаю. Т.е. настроив breakpoint один раз, пользуюсь им всё время.
Но нужно знать 2 вещи. Во-первых, без отладчика эта история не работает. Во-вторых, даже с отладчиком эта история не работает, если у вас mssql aka SQL Server.
Надеюсь, внимательные читатели заметили, что breakpoint стоит не абы где, а на программном логировании, а значит можно просто включить соответствующий уровень логирования в консоль или в файл и получить похожий результат, просто поменяв пару строк кода. Но как это делается вы, наверное, и без меня знаете.
Top comments (0)