У меня странное поведение ActiveRecord (возможно, в сочетании с сервером MySQL). Существует огромная таблица (сотни миллионов записей). Если я сделаю этот простой вызов:
SearchResult.where(id: ids[0..15000]).select('uid').to_a
... это займет не более 1 секунды.
Теперь, если я сделаю этот звонок:
SearchResult.where(id: ids[0..16000]).select('uid').to_a
... это может занять минуты!
Хотя в то же время, если я запускаю следующие два запроса, чтобы получить все записи по 16 тыс., Он работает ровно в течение 1 секунды:
SearchResult.where(id: ids[0..15000]).select('uid').to_a +
SearchResult.where(id: ids[15001..16000]).select('uid').to_a
Более того, если я вызову .to_sql
для длительной команды и выполню ее напрямую с помощью команды mysql или MySQL Workbench - это займет даже меньше секунды.
Я запустил ANALYZE TABLE, а затем попробовал EXPLAIN как напрямую, так и через ActiveRecord, и они идентичны. В обоих случаях используется ВСЕ сканирование (полное сканирование таблицы). Разница лишь в том, что он работает хорошо напрямую, но зависает при выполнении через ActiveRecord. Теперь самое интересное - если я заставлю использовать индекс PRIMARY - он начнет хорошо работать через ActiveRecord, но это не решение, потому что я не могу использовать его с предварительной загрузкой ассоциаций ActiveRecord.
Это странное поведение действительно ставит меня в тупик, потому что я использую много предварительных загрузок ассоциаций ActiveRecord (например, .includes(searches: :search_results)
), которые иногда заканчивают запросом десятков тысяч записей (да, мне действительно все они нужны), и тому подобное Запрос останавливается на несколько минут. Я бы просто использовал принудительное использование индекса, но это не решает проблему в других местах, создает больше проблем в других, и тогда я не смогу использовать предварительную загрузку ActiveRecord. Есть идеи?