Отчёт по выручке сч...
 
Уведомления
Очистить всё

Отчёт по выручке считается 14 секунд. Я аналитик, на Ruby пишу мало

5 Сообщения
5 Пользователи
6 Реакции
297 Просмотры
Заур74
Сообщения: 3
Автор темы
Пишет в irb аналитик
Присоединился: 1 год назад
[#89]

Обычно пишу SQL, но тут попросили поправить отчёт в админке, который считает выручку по категориям за месяц. Открывается 14 секунд. Код:

orders = Order.where(created_at: month_range).includes(:items)
totals = Hash.new(0)
orders.each do |order|
  order.items.each do |item|
    totals[item.category_id] += item.price * item.quantity
  end
end

Заказов за месяц около 120 тысяч, позиций под 400 тысяч. Понимаю, что считать надо в базе, но как это записать в Active Record, не уходя в голый SQL?


4 ответа
TimurK62
Сообщения: 31
Читает чужие PR бэкенд-разработчик
Присоединился: 3 года назад

Сейчас вы тянете в Ruby больше полумиллиона объектов, чтобы сложить числа. Группировка в базе:

totals = OrderItem
  .joins(:order)
  .where(orders: { created_at: month_range })
  .group(:category_id)
  .sum(Arel.sql("order_items.price * order_items.quantity"))

Один запрос, на выходе хэш { category_id => сумма }, вьюху переделывать почти не придётся. Проверьте ещё индексы на orders.created_at и order_items.order_id.


Ответ
lena_bogatyreva
Сообщения: 27
Читает чужие PR бэкенд-разработчица
Присоединился: 3 года назад

Сохранила, очень наглядно, как два вложенных each превращаются в один запрос


Ответ
kostya.sokurov
Сообщения: 73
Держит прод бэкенд-разработчик, senior
Присоединился: 4 года назад

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


Ответ
katrin47
Сообщения: 4
Пишет в irb бэкенд-разработчица
Присоединился: 3 года назад

и month_range лучше брать через Time.current.all_month, а не собирать руками: с датами вместо времени легко потерять последний день месяца


Ответ