Это связано с вопросом год и изменение назад .
Я привел пример вопроса, который должен работать из коробки, при условии, что у вас есть sqlite3: https: // github. com / cairo140 / rails-eager-loading-counts-demo
git clone git://github.com/cairo140/rails-eager-loading-counts-demo.git
cd rails-eager-loading-counts-demo
rails s
У меня есть более полная запись в репозитории, но мой общий вопрос таков.
Как можно Я делаю Rails нетерпеливым подсчетом нагрузки таким образом, чтобы минимизировать количество запросов к базе данных по всем направлениям?
Проблема n + 1
возникает всякий раз, когда вы используете #count
в ассоциации, несмотря на то, что включили эта ассоциация через #includes (: associated)
в ActiveRelation. Обходной путь - использовать #length
, но это хорошо работает только тогда, когда объект, для которого он вызывается, уже загружен, не говоря уже о том, что я подозреваю, что он дублирует что-то, что уже сделали внутренние компоненты Rails. Также, проблема с использованием #length
заключается в том, что это приводит к нежелательной перегрузке, когда ассоциация не была загружена с самого начала, а счет - это все, что вам нужно.
Из файла readme:
Мы Можно избежать этой проблемы, запустив #length в массиве сообщений (см. приложение), который уже загружен, но было бы неплохо, если бы также был доступен счетчик. Он не только более последовательный; он обеспечивает путь доступа, который не обязательно требует загрузки сообщений. Например, если у вас есть партиал, который отображает счет, несмотря ни на что, но половину времени партиал вызывается с загруженными сообщениями, а половину - без него, вы сталкиваетесь со следующим сценарием:
- Использование
#count
- n
COUNT
запросов стиля, когда сообщения уже загружены- n
COUNT
запросов стиля, когда сообщения еще не загружены- Использование
#length
- Отсутствие дополнительных запросов, когда сообщения уже загружены
- n
*
запросов стиля, когда сообщения еще не загруженыМежду этими двумя вариантами нет доминирующего варианта. Но было бы неплохо изменить #count, чтобы отложить его до #length или получить доступ к длине, которая хранится каким-либо другим способом за кулисами, чтобы мы могли иметь следующий сценарий:
- Использование исправленного
#count
- Zero дополнительные запросы, когда сообщения уже загружены
- n
COUNT
запросов стиля, когда сообщения еще не загружены
Итак, какой здесь правильный подход? Есть что-то, что я упустил (очень, очень вероятно)?