TGViewer
Организованное программирование | Кирилл Мокевнин Организованное программирование | Кирилл Мокевнин @orgprog · 14.3K subscribers
Post #432 11.9K
Кейс про ии, n+1 и orm

Все опытные бекендеры так или иначе знают, что sql-запросы в цикле это зло. Но даже если их явно не делать, то они все равно будут появляться при использовании ORM. Например мы извлекаем какую-то связь, а затем генерируем json по этому набору данных, попутно вызывая какие-то вложенные связи: user.companies().map((company) => company.creator()). В этом примере сами компании будут извлечены одним запросом, но обращение к creator() породит цепочку запросов, по запросу на каждую компанию. В миру эта штука называется select n + 1

Кто-то скажет что фу, orm зло, потому что там есть такая проблема. Я к этому отношусь не так, orm позволяет быстро двигаться вперед, а n+1 обычно чинится очень просто, за счет механизмов подгрузки связей в orm. Например так: user.companies.includes(:creator).map.... Несмотря на это, у нас на Хекслете действительно десятки мест где такая проблема есть. Чаще всего она не критическая, поэтому мы чиним по мере появления проблем.

Хорошая новость заключается в том, что если у вас ORM, то возможно написать инструмент, который будет находить n + 1 самостоятельно почти для всех ситуаций. Так как мы пишем на Rails, то используем гем Bullet, который добрые люди написали довольно давно как раз под эту задачу. Он не просто показывает где n+1, но конкретно говорит как его убрать:


user: kirillmokevnin
GET /programs/algorithms-extended
USE eager loading detected
Stack::Landing::LearningModule => [:project_cover_attachment]
Add to your query: .includes([:project_cover_attachment])
// тут еще стек вызовов для удобства


Не всегда все чинится так просто по рекомендации, потому что само исправление может быть следствием, а причина неправильные связи, неправильная работа с данными и т.п. Но в целом, оно помогает ну очень сильно.

На днях, когда стало видно, что было много изменений за последний месяц, которые породили немало тяжелых n+1. Думаю дай выделю часик и пройдусь по ним. Открываю код и понимаю что елки палки, так это ведь идеальная задача под ИИ. Написал запрос и запустил на выполнение в режиме если найден n+1 то бросаем исключение:

> Запускай тесты по очереди, исправляй исключение n+1 (bullet) по рекомендации. Если тест после этого снова не проходит, переходи к следующему

Это надо было сделать, чтобы не виснуть на тех местах, где нужно ручное вмешательство в его идеи по тому как починить (тут он без подсказок не справится). В общем 20 минут работы, десятки контроллеров поправлены. Дальше осталась только админка, поэтому отложил на следующий раз.

Ссылки: Телеграм | Youtube | VK
Telegram Организованное программирование | Кирилл Мокевнин Делюсь опытом и обучаю. И ИИ? И ИИ. Ютуб https://youtube.com/@mokevnin AI Клуб @hexletclub | Внедрение AI в SDLC https://praxor.ru/ Для предложений в личку канала
  • 👍 79
  • ❤ 17
  • 🔥 10
  • 🤡 5
  • 🤔 3
  • ⚡ 1
  • 🗿 1
More from @orgprog
  1. Sep 27, 2026Выпуск опубликован, можно смотреть и слушать. Сегодня в подкасте создатель Вастрик Клуба В…
  2. Sep 26, 2026Костные наушники Под каждым видео коммент, что за наушники ты носишь? Это костные наушники…
  3. Sep 24, 2026Статистика участия в опенсорсе Активно разрабатывая я регулярно наыткаюсь на баги и не дор…
  4. Sep 21, 2026Банда четырех для эпохи агентов Количество паттернов по тому, как эффективно работать с ИИ…
  5. Sep 16, 2026Главное правило принятия архитектурных решений Когда-то давно в одной из книжек я прочитал…
  6. Sep 13, 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 →