DEV Community

Гимаев Наиль
Гимаев Наиль

Posted on

1

Отладчик Pycharm против проблемы 1+N

Лирика

К примеру, требуется вывести в 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, то я всегда включаю вывод логов отладчика, чтобы видеть обращение к БД. Я покажу как это делается, но перед этим вам нужно прочитать


Прочитали? Тогда начинаем.
  1. Откройте свой проект django и перейдите по ссылке CursorDebugWrapper.execute или CursorDebugWrapper.debug_sql если у вас Django 3+
  2. Поставьте breakpoint на logger.debug
  3. Сделайте правый клик на красном кружке
  4. В появившимся диалоге отключите Suspend
  5. Включите Evalute and log и напишите '(%.3f) %s; args=%s'%(duration, sql, params)

Должно получится так:

Screenshot of Pycharm

Теперь, если вы запустите проект под отладчиком, то увидите в консоли все запросы к БД и время их выполнения. В моём проекте запросов в БД от вызова одного API не очень много и 1+N сразу бросается в глаза, если не включен cacheops. Отключайте cacheops на машине разработки, тогда неправильные запросы к БД вы будете буквально чувствовать на собственной шкуре без всякого логирования и не допустите плохой код в проект.
Главная прелесть логирования через отладчик в том, что не требуется вносить изменения в код, и не придётся убирать за собой забытые print'ы. При этом я не удаляю breakpoint, когда он мне не нужен, а просто выключаю (Ctrl+Shift+F8). А когда становится нужен, снова включаю. Т.е. настроив breakpoint один раз, пользуюсь им всё время.

Но нужно знать 2 вещи. Во-первых, без отладчика эта история не работает. Во-вторых, даже с отладчиком эта история не работает, если у вас mssql aka SQL Server.

Надеюсь, внимательные читатели заметили, что breakpoint стоит не абы где, а на программном логировании, а значит можно просто включить соответствующий уровень логирования в консоль или в файл и получить похожий результат, просто поменяв пару строк кода. Но как это делается вы, наверное, и без меня знаете.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay