Обновить

Предзагрузил пачкой — получил N² запросов. Как expire_on_commit превращает оптимизацию в квадрат

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели7.9K
Всего голосов 5: ↑4 и ↓1+7
Комментарии4

Комментарии 4

ORM с сущностями в целом часто скрывает подобные проблемы. Работать просто с SQL в таких сценариях выходит проще - запрос пишется точечно под сценарий, данные простые на входе и на выходе.

Согласен, по итогу мы примерно туда и пришли: выборка нужных колонок, значения в кортежах, bulk UPDATE. Фактически тот же SQL, просто через Core.

Мне кажется, водораздел проходит не между ORM и SQL, а между типами кода. В обычных ручках API объекты удобнее: транзакция короткая, сущность одна, читается лучше. А в фоновом проходе по всей базе, где чтение и запись вперемешку, ORM прячет цену. Причём прячет так, что заметно её только счётчиком запросов.

Интересный кейс, особенно момент с реальным подсчётом запросов. Только при общем UPDATE после рассылки может появиться другая проблема: если процесс отправит половину уведомлений и упадёт, при следующем запуске они уйдут повторно. У вас отправка идемпотентная или такие повторы допустимы?

Да, всё так, это осознанный at-least-once.

Окно, правда, узкое. Флаг ставится только если отправка реально прошла: вернулась ошибка, id в пачку не попал и уйдёт следующим тиком. И коммит не в конце всего прохода, а после каждого тренера. То есть при падении процесса теряется максимум пачка одного человека, обычно одно-три напоминания, а не половина рассылки.

Цена дубля тут небольшая, лишнее «через час тренировка». Пережить можно, поэтому сознательно живём с повтором.

А вот где нельзя, это деньги. Там механизм другой: атомарный UPDATE … SET applied = true WHERE applied = false и проверка, сколько строк реально обновилось. Начисляем, только если строка досталась нам. Повторная доставка вебхука на этом и гасится.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации