Ответ вслух Junior EXPLAIN и оптимизация спрашивают часто обновлено

Проблема N+1

Вопрос

Объясни проблему N+1: как она возникает, как её заметить и как исправить.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

N+1 это когда мы получаем список одним запросом, а потом в цикле для каждого элемента делаем ещё по запросу: 50 статей и 50 запросов за авторами. Каждый запрос быстрый, но вместе это десятки походов по сети, и время растёт вместе с размером страницы.

Что должно прозвучать в ответе

  • Один запрос за списком и по запросу на каждый элемент за связанными данными

  • Типично возникает из-за ленивой загрузки в ORM в цикле

  • Заметить: число запросов растёт с размером списка, логи SQL, APM, счётчик запросов в тестах

  • Исправить: JOIN, запрос по списку id (IN или ANY), eager loading, DataLoader в GraphQL

  • Следить, чтобы JOIN не размножил строки и не тянул лишнее

Что могут спросить следом

  • Как DataLoader решает N+1 в GraphQL?
  • Когда JOIN хуже двух отдельных запросов?

Разбор

N+1 это когда мы получаем список одним запросом, а потом в цикле для каждого элемента делаем ещё по запросу: 50 статей и 50 запросов за авторами. Каждый запрос быстрый, но вместе это десятки походов по сети, и время растёт вместе с размером страницы. Чаще всего так происходит из-за ленивой загрузки в ORM: обращаемся к article.author в цикле, а ORM тихо ходит в базу. Замечаю по логам SQL или APM, где видно много одинаковых запросов с разными id; в тестах можно считать число запросов на эндпоинт. Исправляю загрузкой пачкой: JOIN, один запрос WHERE id = ANY($1) по собранным id, eager loading в ORM (include в Prisma, relations в TypeORM), в GraphQL DataLoader. С JOIN слежу, чтобы связь один ко многим не размножила строки; иногда два запроса, список и связанные данные по id, проще и дешевле.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме