Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке корельований підзапит і коли його краще переписати?

Корельований підзапит посилається на колонки зовнішнього запиту, тож логічно виконується для кожного рядка зовнішнього запиту:

SELECT u.id, u.name,
       (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS orders_count,
       (SELECT MAX(created_at) FROM orders o WHERE o.user_id = u.id) AS last_order_at
FROM users u;

Звичайний (некорельований) підзапит не залежить від зовнішнього і виконується один раз: WHERE id IN (SELECT user_id FROM vip_list).

Чим корельовані підзапити можуть бути погані: на 100 000 користувачів - 200 000 виконань підзапитів. З індексом на orders.user_id кожне швидке, але сумарно це багато роботи. Без індексу - катастрофа.

Як переписують:

-- JOIN з агрегованою похідною таблицею: orders проходиться один раз
SELECT u.id, u.name,
       COALESCE(s.orders_count, 0) AS orders_count,
       s.last_order_at
FROM users u
LEFT JOIN (
    SELECT user_id, COUNT(*) AS orders_count, MAX(created_at) AS last_order_at
    FROM orders
    GROUP BY user_id
) s ON s.user_id = u.id;

Але не завжди варто переписувати:

  • Оптимізатор MySQL сам перетворює багато підзапитів з IN / EXISTS на semi-join і виконує їх як з'єднання.
  • Для сторінки з 20 рядків корельований підзапит виконається 20 разів - це дешевше, ніж агрегувати всю таблицю замовлень.
  • Корельований EXISTS з індексом зупиняється на першому знайденому рядку - часто найефективніший спосіб перевірки.

Правило: дивитися EXPLAIN і час на реальних даних. Підзапит у SELECT для кожного рядка великої вибірки - підозрілий; EXISTS у WHERE з індексом - зазвичай у порядку.

У Laravel withCount('orders') генерує саме корельований підзапит - для пагінованих списків це нормально.

Докладніше в документації: Корельовані підзапити

1

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання