Вы считаете число заказов по таблице orders, добавили JOIN к таблице order_items и получили подозрительно большой результат. В EXPLAIN оценка числа строк после соединения сильно выше входной. Что это чаще всего означает?
A
EXPLAIN сообщает точное время выполнения, и рост rows ведёт к росту отклика в той же пропорции в реальной системеBСвязь один-ко-многим размножает строки в
JOIN, и COUNT(*) считает позиции вместо заказов; нужен COUNT(DISTINCT orders.id)CИндекс на ключе соединения отсутствует, без индекса
COUNT(*) теряет корректность и результат восстановить нельзяDБаза «потеряла» первичный ключ таблицы
orders, и план оптимизатора перестаёт учитывать уникальность строк по ключуПравильный ответ. План помогает заметить размножение строк из-за
JOIN и связать это с корректностью агрегатной метрики.Разбор
Если после JOIN ожидаемое число строк резко растёт, это часто нормальное следствие отношения один-ко-многим. Для аналитики важно, что агрегат может начать считать не то — например, позиции вместо заказов. EXPLAIN сам по себе не доказывает корректность, но подсказывает место, где возникает кратность и где стоит пересмотреть агрегацию или применить COUNT(DISTINCT). Гипотезы про «отсутствие индекса» или «потерю первичного ключа» — частые мифы, не объясняющие наблюдение.
Проверь себя · 1/3разбор после ответа
Есть индекс по
orders.created_at, но EXPLAIN для фильтра WHERE date(created_at) = current_date показывает Seq Scan. Почему это часто происходит?Ещё вопросы по теме «EXPLAIN и оптимизация»
- Вы хотите добавить новый запрос в дашборд и боитесь, что он сильно нагрузит базу, потому что таблица `events` очень большая. Что даёт запуск `EXPLAIN` для этого запроса?
- В выводе `EXPLAIN` вы видите узел `Seq Scan on orders`. Что это обычно означает в плане выполнения запроса?
- В плане `EXPLAIN` для запроса по пользователю вы видите проход по индексу `orders_user_id_idx` для таблицы заказов. Какой вывод наиболее корректен?
- На большой таблице `events` запрос `SELECT * FROM events ORDER BY created_at DESC LIMIT 100` неожиданно работает быстро. Какое объяснение наиболее вероятно при наличии индекса по `created_at`?
- Есть индекс по `orders.created_at`, но `EXPLAIN` для фильтра `WHERE date(created_at) = current_date` показывает `Seq Scan`. Почему это часто происходит?
- Все вопросы по «EXPLAIN и оптимизация» →