Выбор ответа Senior Django ORM и N+1 обновлено
Обработка миллиона строк
Вопрос
Management-команда обходит 5 млн записей for row in Event.objects.all(): и падает по памяти. Что поможет?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: .iterator(chunksize=2000): порции без кеширования QuerySet. Обычный обход QuerySet загружает и кеширует все объекты в памяти. iterator() отключает кеш результата и на PostgreSQL использует серверный курсор, отдавая строки порциями.
Варианты ответа
.all().all(), чтобы сбросить кеш предыдущего QuerySetlist(Event.objects.all()), чтобы загрузить всё одним запросом.order_by("?"), чтобы база отдавала строки без сортировки в памяти.iterator(chunk_size=2000): порции без кеширования QuerySetправильный ответ
Разбор
Обычный обход QuerySet загружает и кеширует все объекты в памяти. iterator() отключает кеш результата и на PostgreSQL использует серверный курсор, отдавая строки порциями. Для массовых изменений ещё лучше update() или пакетная обработка по диапазонам id. list() усугубит проблему, а order_by("?") это медленная случайная сортировка.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Django ORM и N+1»
- Задвоение сумм при нескольких annotate
- Посчитать SQL-запросы при ленивой загрузке
- Как prefetch_related склеивает данные
- exists() и count() вместо загрузки строк
- Атомарное увеличение счётчика
- Prefetch с вложенным select_related
- transaction.atomic
- Когда выполняется QuerySet