TGViewer
EvApps EvApps @evapps_team · 198 subscribers
Post #1519 104
⚡️ Бэкенд тормозит? Скорее всего это N+1
Когда какой-нибудь эндпоинт вдруг начинает отвечать по полсекунды, все первым делом лезут оптимизировать код: асинхронщина, воркеры, микрооптимизации.
А причина обычно куда скучнее — ты просто дёргаешь базу сотню раз там, где хватило бы одного запроса.

🐘 Как выглядит N+1 Берём список из 50 заказов и для каждого лезем за пользователем:
orders = Order.all            # 1 запрос — забрали заказы
for o in orders:
print(o.user.name) # +50 запросов, по одному на заказ

Один запрос на список и ещё по одному на каждую строку.
Отсюда и название — N+1.
На локалке с десятком записей ты это даже не заметишь.
А на проде, где строк тысячи и база стоит на другом сервере, каждый такой поход — это отдельный сетевой запрос туда-обратно.
Вот они и набегают в те самые полсекунды.

🔧 Как чинить Идея одна: вытащить всех пользователей сразу, одним-двумя запросами, а не по штучке в цикле.
В разных ORM это включается по-разному:
# Django
Order.objects.select_related("user")

# SQLAlchemy
session.query(Order).options(joinedload(Order.user))

# Rails
Order.includes(:user)

Под капотом это либо JOIN, либо второй запрос вида WHERE user_id IN (...).
Было 51 обращение — стало два.
На реальных данных разница огромная.

🔍 Как заметить Беда в том, что глазами N+1 не видно — код выглядит чистым.

Поэтому: — смотри SQL-лог в дев-режиме: если на один запрос к API летит пачка одинаковых SELECT-ов — вот он, красавец; — поставь профайлер (django-silk, bullet, rack-mini-profiler) — они прямо тычут носом; — или тупо считай запросы на эндпоинт.
Больше десятка на простую страницу — уже звоночек.

💾 И про кэш, пока не разогнались
Как только заходит разговор про скорость, все сразу хотят прикрутить Redis.
Но кэш — это не «сделать быстро», это «отложить проблему и получить новую»: теперь надо думать, когда его чистить.
Прежде чем кэшировать, честно ответь себе: — эти данные вообще часто читают и редко меняют?
если нет — кэш ни к чему; — что будет, когда они устареют и я отдам юзеру старьё? — как я вообще пойму, что пора обновлять кэш?

Часто выходит, что убрать N+1 и повесить нормальный индекс дают те же 200 мс выигрыша — только без лишнего слоя, который потом будет отдавать неактуальные данные и портить тебе вечера.
Правило простое: сначала померь и убери явную дичь в запросах, и только потом тащи кэш.
Наоборот — почти всегда дорога к боли.

#backend #performance #database #orm #optimization #dev
More from @evapps_team
  1. Sep 21, 2026🧩 Что тут не так? Код-загадка Формат новый - показываю код, ты угадываешь подвох, ниже ра…
  2. Sep 18, 2026🎭 Мифы про производительность, в которые верят даже опытные Миф 1: "Меньше строк кода - б…
  3. Sep 16, 2026🚨 Как перевод денег уронил нам прод ⏰ 19:10 Задеплоили долгожданное - переводы между коше…
  4. Sep 14, 2026🗃 Кэш поставили, а он отдаёт старьё В программировании две сложные вещи - инвалидация кэш…
  5. Sep 11, 2026🔌 "Too many connections" - и почему база падает под нагрузкой Под нагрузкой прилетает FAT…
  6. Sep 11, 2026Пока вы наслаждаетесь пятницей, мы напоминаем, что уже завтра стартует одна из наших любим…
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 →