TGViewer
Симулейтив Симулейтив @simulative_official · 7.44K subscribers
Post #2619 1.57K
Экспресс-оптимизация SQL-запроса на реальном кейсе

Привет! На связи Владимир Лунев, ментор тренинга «Продвинутый SQL». Давайте разберём кейс, где простые приёмы оптимизации могут ускорить выполнение запроса в несколько раз.

Представим, что у нас есть база заказов крупного интернет-магазина с реальными объёмами данных. Индексов нет. Всё выполняется на сырых таблицах. СУБД PostgreSQL.

Задача: посчитать для каждой категории количество заказов, суммарную выручку и средний чек за август 2025 только для завершённых заказов (со статусом completed).

Состав БД:
Таблица orders (5 млн строк) с полями:
➖ id — уникальный идентификатор заказа;
➖ product_id — ID продукта;
➖ order_date — дата заказа;
➖ amount — сумма заказа;
➖ status — статус заказа, например, completed.

Таблица products (2 тыс. строк):
➖ id — ID продукта;
➖ category_id — ID категории;
➖ price — цена.

Таблица categories (100 строк):
➖ id — ID категории;
➖ name — название категории.

Исходный запрос (медленный), ожидаемое время выполнения 4-5 минут:
SELECT 
c.id, # идентификатор категории
c.name AS category, # название категории
COUNT(o.id) AS orders_count, # количество заказов
SUM(o.amount) / COUNT(o.id) AS avg_check # средний чек (ручное деление)
FROM orders o
JOIN products p ON o.product_id = p.id # соединяем с таблицей продуктов
JOIN categories c ON p.category_id = c.id # соединяем с категориями
WHERE
o.status = 'completed' # фильтруем только завершённые заказы
AND o.order_date >= '2025-08-01' # начало периода (строковый литерал)
AND o.order_date < '2025-09-01' # конец периода
GROUP BY c.id, c.name # группировка по категории (строка и id)
ORDER BY SUM(o.amount) DESC; # сортировка по суммарной выручке


Почему медленно:
➖ JOIN происходит на 5 млн строк без фильтрации.
➖ GROUP BY по c. name — сравнение строк (TEXT) вместо чисел, это дополнительная нагрузка.
➖ AVG считается вручную (SUM / COUNT) — выполняется две агрегации.
➖ Фильтр по дате задан как строка — типы приводятся динамически, что замедляет план выполнения.

Оптимизированный запрос (быстрее в ~10 раз!), ожидаемое время выполнения 25-30 секунд:
WITH filtered_orders AS (
# Сначала фильтруем все нужные заказы в отдельном CTE
SELECT *
FROM orders
WHERE status = 'completed' # только завершённые
AND order_date >= DATE '2025-08-01' # явное указание типа DATE
AND order_date < DATE '2025-09-01'
)
SELECT
c.id, # id категории
c.name AS category, # название категории
COUNT(fo.id) AS orders_count, # количество заказов
SUM(fo.amount) AS total_sales, # суммарная выручка
AVG(fo.amount) AS avg_check # средний чек (встроенная функция)
FROM filtered_orders fo
JOIN products p ON fo.product_id = p.id # соединяем уже отфильтрованные заказы
JOIN categories c ON p.category_id = c.id # соединяем с категориями
GROUP BY c.id # PK, группировка по ID (name подтянется автоматически)
ORDER BY total_sales DESC; # сортировка по суммарной выручке


Что изменилось и почему быстрее:
➖ CTE filtered_orders — с EXPLAIN ANALYZE видно, что количество строк на JOIN сократилось примерно до ~500 тыс. строк вместо 5 млн, т. е. 90%!
➖ GROUP BY c.id — сравнение по числу вместо текста, PostgreSQL подтягивает c.name автоматически.
➖ AVG() вместо SUM/COUNT — встроенная оптимизация движка.
➖ Явное указание типа даты (DATE '2025-08-01') — СУБД не тратит время на приведение типов.

На больших таблицах корректная структура запроса может кардинально влиять на скорость выполнения. В результате правильно построенный запрос может обрабатываться в 10-100 раз быстрее, чем прямой вариант с лишними вычислениями и сортировками.

❗️ Оптимизация SQL — это понимание того, как СУБД выполняет операции и как конкретный юзер может эффективно сэкономить свое время и бонусом ресурсы сервера. Ещё больше кейсов и рекомендаций будет на вебинаре 24 сентября — приходите, расскажу про свои способы оптимизации SQL-запросов.


➡️ Зарегистрироваться на вебинар

📊 Simulative
  • 🔥 23
  • ❤ 6
More from @simulative_official
  1. Oct 14, 2026Post #3620
  2. Oct 13, 2026💻💻💻💻💻 Падение продаж: как аналитик превращает размытый вопрос в расследование? Руково…
  3. Oct 13, 2026💻 Почему ваш SQL-запрос выполняется не так, как вы его написали? Кажется логичным, что ба…
  4. Oct 12, 2026#проанализировали_и_поняли
  5. Oct 11, 2026❗️ Перенос вебинара с Евгением Буториным Друзья, к сожалению, по техническим причинам пере…
  6. Oct 9, 2026💻💻💻💻💻 Как выбрать своё направление в аналитике? Решаешь войти в аналитику, открываешь…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →