Оптимизируйте SQL-запрос, чтобы устранить проблему N+1 в Ruby on Rails и Mysql

Есть 2 модели BuyerOrder и BuyerOrder с отношением 1 ко многим.

class Buyer < ApplicationRecord
  has_many buyer_orders
end

class BuyerOrder < ApplicationRecord
  belongs_to buyer
end

Мне нужно получить общее количество покупателей_заказов и имя покупателя с группой по покупателю_id. Я могу получить необходимые данные по запросу ниже. Buyer.all.map{|buyer| {buyer.id => {buyer_name: buyer.name, total: buyer.buyer_orders.count}}} Результат этого запроса:

[{1=>{:buyer_name=>"Buyer 1", :total=>58}},
 {2=>{:buyer_name=>"Buyer 2", :total=>10}},
 {3=>{:buyer_name=>"Buyer 3", :total=>4}}]

Но этот запрос имеет проблему N+1. Как можно оптимизировать запрос, чтобы устранить проблему N+1? Моя версия Rails — 6.0.3.2, а версия Mysql — 8.0.33.

Может ли кто-нибудь помочь мне решить мою проблему?

Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Используйте метод includes, чтобы загрузить ассоциацию в результат запроса, также используйте size, вместо count, size проверьте, загружена ли ассоциация перед вызовом базы данных.

Buyer.all.includes(:buyer_orders).map{ |buyer| { buyer.id => { buyer_name: buyer.name, total: buyer.buyer_orders.size }}}

Спасибо за Ваш ответ. запрос count все еще выполняется несколько раз.

Bhanu Pratap Singh 07.07.2023 10:56

Я отредактировал свой ответ, попробуйте использовать size вместо count

kaminskil1337 07.07.2023 11:07

Я думаю, что вы должны использовать BuyerOrder в качестве отправной точки вместо Buyer, потому что из BuyerOrder вы уже можете сгруппировать их по атрибуту buyer_id.

Следующий запрос отправится 2 раза в базу данных, независимо от того, сколько у вас Buyers или BuyerOrders:

BuyerOrder.group(:buyer).count.map { |buyer| { buyer[0].id => { buyer_name: buyer[0].buyer_name, total: buyer[1]} } }

Это даст желаемый результат без проблемы N+1.

Другие вопросы по теме