Добавить в корзинуПозвонить
Найти в Дзене
Библиотека программиста

👾🔍 Укрощение монстров: мониторинг и управление ресурсоемкими запросами в Django + PostgreSQL

Каждый Django-разработчик рано или поздно сталкивается с неожиданно «тяжелыми» запросами, способными превратить быстрое приложение в неповоротливого слона. Рассказываем, как с помощью django-pgactivity выследить и обезвредить такие запросы, прежде чем они создадут проблемы вашим пользователям. Этот материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест. 📧 Подписаться (function () { let link = document .getElementById ("eabaf85f-427a-40a4-9baf-756cecd004eb-https://proglib.io/w/bb4fad41-2"); if (! link) return; let href = link .getAttribute ("href"); if (! href) return; let prefix = link .dataset .prefix; let action = link .dataset .action; link .addEventListener ("click", function (e) { let data = new FormData (); data
Оглавление

Каждый Django-разработчик рано или поздно сталкивается с неожиданно «тяжелыми» запросами, способными превратить быстрое приложение в неповоротливого слона. Рассказываем, как с помощью django-pgactivity выследить и обезвредить такие запросы, прежде чем они создадут проблемы вашим пользователям.

Этот материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.

📧 Подписаться

(function () { let link = document .getElementById ("eabaf85f-427a-40a4-9baf-756cecd004eb-https://proglib.io/w/bb4fad41-2"); if (! link) return; let href = link .getAttribute ("href"); if (! href) return; let prefix = link .dataset .prefix; let action = link .dataset .action; link .addEventListener ("click", function (e) { let data = new FormData (); data .append ("url", href); apiFetch (action, { method: "POST", body: data }) .then (function (res) {}) .catch (function (err) { console .error (err); }); }) })();

Ресурсоемкость и продолжительность некоторых (невинных на первый взгляд) запросов может стать неприятным сюрпризом для разработчиков. Основная причина этой проблемы – сложные конструкции, включающие JOIN и условия, такие как LIKE, которые усложняются авторизационной системой и дополнительной обработкой:

Если несколько пользователей выполняют такие ресурсоемкие запросы одновременно, производительность приложения ощутимо ухудшается. Среди возможных решений этой проблемы:

  • Оптимизация конкретных медленных запросов – это подразумевает анализ SQL-запросов и оптимизацию их структуры. Например, можно попробовать индексировать часто используемые поля.
  • Изменение авторизационной системы – иногда система авторизации накладывает дополнительные условия на запросы, что может усложнять их выполнение. Упрощение этих условий может ускорить выполнение.
  • Ограничение сложных запросов – можно ввести ограничения на типы запросов, которые могут выполняться, например, запретить использование LIKE-запросов для полей, не имеющих индексов.

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

💻 Библиотека программиста

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека программиста»

Решение с использованием django-pgactivity

Для мониторинга и управления долгими запросами в Django используется библиотека django-pgactivity. Она позволяет отслеживать активные запросы, длительность их выполнения, и даже завершать их при необходимости.

Настройка мониторинга длительных запросов

Команда для запуска мониторинга всех активных запросов, выполняющихся более 1 минуты:

-2

Эта команда выведет список запросов, отображая их идентификаторы, статус и время выполнения. Это позволяет увидеть, какие запросы зависают и какие могут требовать оптимизации:

-3

Трассировка запросов до их исходной точки

Одна из самых крутых возможностей django-pgactivity – добавление контекста к SQL-запросам. Это позволяет привязать запрос к URL и HTTP-методу, вызвавшему его. Благодаря этому разработчики смогут видеть, откуда именно в приложении пришел медленный запрос, и сразу начнут оптимизацию в конкретном месте:

-4

Установка тайм-аута для запросов

Чтобы предотвратить выполнение длительных запросов, можно установить тайм-аут для конкретных функций. Например, можно использовать декоратор @pgactivity.timeout(60), который завершает любой SQL-запрос в пределах этой функции, если он выполняется более 1 минуты:

-5

Если запрос превысит лимит в 1 минуту, будет вызвано исключение OperationalError, и запрос будет отменен на уровне PostgreSQL – это позволит избежать перегрузки сервера и вернет пользователю информативное сообщение об ошибке.

Оптимальный подход

Максимальную производительность Django-приложения на базе PostgreSQL обеспечивают:

  • Мониторинг и идентификация медленных запросов с помощью django-pgactivity.
  • Установка тайм-аутов на уровне функций, чтобы долгие запросы завершались автоматически.

Такой подход к управлению производительностью базы данных позволяет разработчикам оперативно выявлять и устранять узкие места в обработке запросов.

***

Статьи по теме