1. Переконайтеся, що є індекси
Якщо ви робите JOIN
по певному стовпцю (id
, user_id
, foreign_key
тощо), переконайтеся, що ці стовпці проіндексовані.
CREATE INDEX idx_users_id ON users(id); CREATE INDEX idx_orders_user_id ON orders(user_id);
🔸 Індекси потрібні для всіх полів, які використовуються в ON
.
🔹 2. Використовуйте EXPLAIN
Перед тим як оптимізувати запит, подивіться його план виконання:
EXPLAIN ANALYZE SELECT * FROM users JOIN orders ON users.id = orders.user_id JOIN payments ON orders.id = payments.order_id JOIN products ON orders.product_id = products.id JOIN categories ON products.category_id = categories.id;
💡 Що аналізувати в EXPLAIN
?
Using temporary
абоUsing filesort
– це погано ❌ref
абоindex
– це добре ✅ALL
(Full Table Scan) – треба уникати ❌
🔹 3. Впорядкуйте JOIN у правильному порядку
Додавайте таблиці в JOIN
так, щоб:
Спочатку були менші таблиці
Основна таблиця була першою (
users
у прикладі)Фільтри (
WHERE
) застосовувалися якомога раніше
🔹 4. Уникайте JOIN для непотрібних даних
Якщо вам потрібні лише агреговані дані, використовуйте EXISTS
, IN
, LEFT JOIN
або GROUP BY
.
❌ Поганий приклад:
SELECT users.id, orders.id FROM users JOIN orders ON users.id = orders.user_id JOIN payments ON orders.id = payments.order_id;
✅ Кращий варіант:
SELECT users.id, orders.id FROM users JOIN orders ON users.id = orders.user_id WHERE EXISTS ( SELECT 1 FROM payments WHERE payments.order_id = orders.id );
❗ EXISTS
швидший за JOIN
, якщо не потрібно забирати дані з таблиці payments
.
🔹 5. Оптимізуйте за допомогою INDEX JOIN (COVERING INDEX)
Іноді достатньо створити складений індекс:
CREATE INDEX idx_orders ON orders(user_id, product_id);
📌 Це зменшить кількість звернень до диска, бо дані знайдуться в індексі.
🔹 6. Перетворіть JOIN у UNION або CROSS APPLY
Якщо JOIN
витягує багато зайвих рядків, розгляньте UNION
:
SELECT id, name FROM users UNION SELECT id, name FROM admins;
Це може бути ефективніше за JOIN
, якщо рядків багато.
🔹 7. Нормалізуйте структуру БД
Якщо у вас забагато
JOIN
, можливо, потрібно переглянути схему БД.Можливо, якісь таблиці потрібно об'єднати (
denormalization
).
🔹 8. Використовуйте MATERIALIZED VIEW (якщо підтримується)
Якщо JOIN
складний і часто використовується, створіть матеріалізоване представлення:
CREATE MATERIALIZED VIEW fast_orders AS SELECT users.id AS user_id, orders.id AS order_id, payments.status FROM users JOIN orders ON users.id = orders.user_id JOIN payments ON orders.id = payments.order_id;
⚡ Це дозволяє уникнути повторних обчислень.
🔥 Висновок
1️⃣ Використовуйте індекси на ключових стовпцях.
2️⃣ Аналізуйте EXPLAIN
– уникати ALL
, Using filesort
, Using temporary
.
3️⃣ Впорядковуйте JOIN
правильно (від малих до великих).
4️⃣ Використовуйте EXISTS
замість JOIN
, якщо не потрібні зайві дані.
5️⃣ Подумайте про денормалізацію або MATERIALIZED VIEW
.
Якщо запит все одно працює повільно – поділіться його EXPLAIN ANALYZE
, і ми знайдемо рішення! 🚀