Ускорьте запрос к базе данных, используя разницу между двумя столбцами: create_at и updated_at - PullRequest
0 голосов
/ 09 мая 2019

В моем проекте Rails у меня есть модель Message, и в моей базе данных хранятся сотни тысяч сообщений. Он также имеет столбец «Статус», который может быть «поставлен в очередь» или «доставлен».

Когда сообщение создается, его статус становится «поставленным в очередь» и, очевидно, поле created_at заполняется. Через некоторое время (я не буду вдаваться в подробности, как), статус этого сообщения станет «доставлено».

Теперь для сотен тысяч сообщений я хочу сгруппировать их по времени доставки. Другими словами, рассчитайте разницу между updated_at и created_at и сгруппируйте их в 0-3 минуты, 3-5 минут, 5-10 минут и более 10 минут.

То, как я сейчас это делаю, это

delivery_time_data = []
    time_intervals = [{lb: 0.0, ub: 180.0}, {lb: 180.0, ub: 300.0}, {lb: 300.0, ub: 600.0},{lb: 600.0, ub: 31*3600*24}]
    time_intervals.each_with_index do |ti, i|
      @messages = Message.where(account_id: @account.id)
                      .where(created_at: @start_date..@end_date)
                      .where(direction: 'outgoing')
                      .where(status: Message::STATUS_DELIVERED)
                      .where('status_updated_at - created_at >= ?', "#{ti[:lb]} seconds")
                      .where('status_updated_at - created_at < ?', "#{ti[:ub]} seconds")
      if i == time_intervals.count - 1
        delivery_time_data.push([i+1, "Greater than #{ti[:lb]/60.to_i} minutes", @messages.count])
      else
        delivery_time_data.push([i+1, "#{ti[:lb]/60.to_i} minutes to #{ti[:ub]/60.to_i} minutes", @messages.count])
      end

Это работает. Но это очень медленно, и когда у меня есть ~ 200000 сообщений, сервер потенциально может выйти из строя.

Если я ожидаю, что сообщения будут создаваться довольно часто, будет ли хорошей идеей добавить индекс в created_at?

Спасибо.

1 Ответ

2 голосов
/ 09 мая 2019

Возможно, вам нужен правильный индекс.

Поля, которые нужно проиндексировать:

  • направление
  • состояние
  • account_id
  • created_at

Поэтому добавьте следующий индекс в миграцию:

add_index :messages, [:direction, :status, :account_id, :created_at]

Некоторые базы данных, в том числе postgresql, могут индексировать выражения. Для достижения наилучших результатов добавьте (updated_at - created_at) в качестве пятого значения к индексу. Вам нужно будет создать это с помощью SQL вместо миграции rails.

Я бы не стал беспокоиться о добавленном времени для создания записей в индексированной таблице. Я просто не стал бы беспокоиться об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...