Какой был самый интересный кейс работы с SQL?

«Какой был самый интересный кейс работы с SQL?» — вопрос из категории SQL и базы данных, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Самый интересный кейс — это рефакторинг и оптимизация монолитного отчета для финансового департамента, который выполнялся более 40 минут. Запрос представлял собой цепочку из 12 вложенных подзапросов и LEFT JOIN по неуникальным полям.

Задача: Рассчитать помесячную динамику LTV (Lifetime Value) для когорт пользователей, с разбивкой по каналам привлечения, учитывая только тех, кто совершил повторные покупки, и исключая тестовые аккаунты.

Исходная проблема: Полное сканирование огромных таблиц orders и users, множественные временные таблицы на диске, неправильные оценки кардинальности оптимизатором.

Мое решение:

  1. Разбил логику на четкие CTE (Common Table Expressions) для читаемости и повторного использования.
  2. Заменил подзапросы в SELECT и JOIN на предварительно агрегированные CTE, чтобы избежать многократного выполнения одной логики.
  3. Ввел оконные функции для расчета накопленного итога внутри когорты, что устранило необходимость в самосоединении (self-join).
  4. Добавил покрывающие индексы (covering indexes) для колонок, используемых в WHERE, GROUP BY и JOIN.

Ключевой фрагмент оптимизированного запроса (на PostgreSQL):

WITH user_cohorts AS (
    SELECT 
        user_id,
        DATE_TRUNC('month', MIN(created_at)) AS cohort_month,
        acquisition_channel
    FROM users
    WHERE is_test_account = FALSE
    GROUP BY user_id, acquisition_channel
),
user_revenue AS (
    SELECT 
        o.user_id,
        DATE_TRUNC('month', o.created_at) AS revenue_month,
        SUM(o.amount) AS monthly_revenue
    FROM orders o
    INNER JOIN user_cohorts uc ON o.user_id = uc.user_id
    WHERE o.status = 'completed'
    GROUP BY o.user_id, DATE_TRUNC('month', o.created_at)
    HAVING COUNT(o.id) > 1 -- Только с повторными покупками
)
SELECT 
    uc.cohort_month,
    uc.acquisition_channel,
    ur.revenue_month,
    SUM(ur.monthly_revenue) OVER (
        PARTITION BY uc.cohort_month, uc.acquisition_channel, ur.user_id 
        ORDER BY ur.revenue_month
    ) AS cumulative_ltv,
    COUNT(DISTINCT ur.user_id) AS active_users
FROM user_cohorts uc
JOIN user_revenue ur ON uc.user_id = ur.user_id
ORDER BY 1, 2, 3;

Результат: Время выполнения сократилось с 40+ минут до ~8 секунд. Это было достигнуто за счет:

  • Резкого уменьшения операций ввода-вывода (I/O).
  • Перехода от Nested Loops Joins к более эффективным Hash Joins.
  • Позволило бизнесу запускать отчет ad-hoc, а не раз в сутки.