TGViewer
SQL Ready | Базы Данных SQL Ready | Базы Данных @sql_ready · 17.5K subscribers
Post #2099 1.9K
Почему коррелированные подзапросы могут снижать производительность SQL-запроса!

Коррелированные подзапросы удобны: внутри них можно обращаться к значениям текущей строки внешнего запроса.

Проблема в том, что оптимизатор может выбрать план, при котором такой подзапрос будет выполняться повторно для каждой строки внешней выборки. На больших объёмах данных это может стать узким местом. Например:
SELECT
u.id,
u.name,
(
SELECT SUM(o.amount)
FROM orders o
WHERE o.user_id = u.id
) AS total_amount
FROM users u;


Если users содержит миллион строк, подзапрос потенциально может быть выполнен миллион раз. Даже при наличии индекса по orders.user_id такой подход иногда становится менее эффективным, особенно в сложных отчётах.

Часто можно сначала агрегировать данные, а затем присоединить результат:
SELECT
u.id,
u.name,
COALESCE(o.total_amount, 0) AS total_amount
FROM users u
LEFT JOIN (
SELECT
user_id,
SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
) o
ON o.user_id = u.id;


Здесь агрегация выполняется один раз, после чего результат соединяется с таблицей пользователей.

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

Для получения последнего заказа пользователя часто используют оконные функции:
SELECT
user_id,
created_at
FROM (
SELECT
user_id,
created_at,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY created_at DESC
) AS rn
FROM orders
) t
WHERE rn = 1;


Но и здесь нет универсального решения. При правильном индексе, например:
(user_id, created_at DESC)


коррелированный запрос вида:
SELECT ...
FROM orders
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT 1;


может быть быстрее, потому что база сможет быстро найти одну нужную строку через индекс.

Делаем вывод: коррелированные подзапросы сами по себе не являются ошибкой. Они могут быть как хорошим решением, так и причиной проблем с производительностью — всё зависит от данных, индексов и выбранного плана выполнения.

🔥 В больших отчётах и высоконагруженных API всегда проверяйте фактический план выполнения. Иногда JOIN, предварительная агрегация или оконные функции позволяют значительно уменьшить количество лишних операций.

➡️ SQL Ready | #практика
  • ❤ 15
  • 👍 7
  • 🔥 4
  • 🤝 3
More from @sql_ready
  1. Oct 5, 2026Проверяйте JSON без преобразования! Если JSON приходит как text, необязательно делать ::js…
  2. Oct 2, 2026Настройте оценку пользовательских функций! Для пользовательской функции PostgreSQL позволя…
  3. Oct 2, 2026🔎 Гибридный поиск в YDB: когда SQL ищет не только по словам В YDB, созданном Yandex B2B T…
  4. Oct 2, 2026😍 SQL-Tutorial — бесплатный учебник по SQL с практическими заданиями! Онлайн-учебник для…
  5. Oct 1, 2026🐱 PostgreSQL Course RU — курс по PostgreSQL и SQL для разработчиков! В репозитории собран…
  6. Sep 30, 2026📂 Шпаргалка по числовым функциям! Например, ROUND() используется для округления значений,…
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 →