Шаблоны создания отчетов в Rails? - PullRequest
10 голосов
/ 18 января 2011

Я создаю несколько отчетов в приложении и наткнулся на несколько способов создания отчетов, и мне хотелось, чтобы вы взяли на вооружение лучшие / распространенные способы создания отчетов, которые можно масштабировать и в режиме реального времени, насколько это возможно.

Во-первых, некоторые условия / ограничения / цели:

  1. Отчет должен обрабатывать данные в режиме реального времени (с помощью node.js или опроса ajax)
  2. Отчет должен обновляться оптимизированным способом
    • Если отчет о просмотрах страниц, а вы получаете тысячи в секунду, может быть не лучше обновлять отчет при каждом просмотре страницы, но, возможно, каждые 10 или 100.
    • Но он все равно должен быть близок к реальному времени (поэтому дневной / почасовой крон не являются приемлемой альтернативой).
  3. Отчет не должен пересчитывать то, что уже рассчитано.
    • Если он имеет счетчик, он увеличивает счетчик.
    • Если у него есть средние значения, возможно, он может каким-то образом обновить среднее значение, не захватывая все записи, которые он усредняет каждую секунду и пересчитывая (пока не уверен, как это сделать).
    • Если он имеет число / среднее значение для диапазона дат ( сегодня , last_week , last_month и т. Д.), И это в режиме реального времени, он не должен не нужно пересчитывать эти средние значения каждую секунду / запрос, каким-то образом выполнять только самые минимальные операции.
  4. Если отчет о записи и «жизненный цикл» записи завершен (скажем, Project, и проект длился 6 месяцев, у него было много активности, но теперь он закончился), отчет следует сохранить на постоянной основе поэтому последующие извлечения просто извлекают предварительно вычисленный документ.

Отчеты не должны быть доступны для поиска, поэтому, когда данные находятся в документе, мы просто отображаем документ. Клиент получает в основном дерево JSON, представляющее все статистические данные, диаграммы и т. Д., Поэтому его можно отобразить в Javascript.

Мой вопрос возникает из-за того, что я пытаюсь найти способ составлять отчеты в реальном времени об огромных наборах данных .

Скажем, я сообщаю об общей регистрации пользователей и активности на сайте. Сайт имеет 1 миллион пользователей, и в среднем 1000 просмотров страниц в секунду. Есть модель User и модель PageView, скажем, где User has_many :page_views. Скажем, у меня есть эти характеристики:

report = {
  :users => {
    :counts => {
      :all        => user_count,
      :active     => active_user_count,
      :inactive   => inactive_user_count
    },
    :averages => {
      :daily      => average_user_registrations_per_day,
      :weekly     => average_user_registrations_per_week,
      :monthly    => average_user_registrations_per_month,
    }
  },
  :page_views => {
    :counts => {
      :all        => user_page_view_count,
      :active     => active_user_page_view_count,
      :inactive   => inactive_user_page_view_count
    },
    :averages => {
      :daily      => average_user_page_view_registrations_per_day,
      :weekly     => average_user_page_view_registrations_per_week,
      :monthly    => average_user_page_view_registrations_per_month,
    }
  },
}

Вещи, которые я пробовал:

1. Где User и PageView оба являются объектами ActiveRecord, поэтому все происходит через SQL.

Я собираю всех пользователей кусками примерно так:

class User < ActiveRecord::Base
  class << self
    def report
      result = {}
      User.find_in_batches(:include => :page_views) do |users|
        # some calculations
        # result[:users]...
        users.each do |user|
          # result[:users][:counts][:active]...
          # some more calculations
        end
      end
      result
    end
  end
end

2. Обе записи MongoMapper::Document объекты

Map-Reduction действительно медленно рассчитывается на месте, и я еще не потратил время, чтобы выяснить, как сделать эту работу в режиме реального времени (см. hummingbird ). По сути, я делаю то же самое: делаю записи на части, добавляю результат в хеш, и все.

3. Каждый расчет - это собственный запрос SQL / NoSQL

Это своего рода подход, который использует Rails статистика gem . Единственное, что мне не нравится в этом, - это количество запросов, которое это может сделать (не проверялось, лучше ли делать 30 запросов на запрос на отчет, чем разбивать все объекты в памяти и сортировать в прямом рубине).

Вопрос

Я полагаю, что вопрос в том, как лучше всего, исходя из вашего опыта, создавать отчеты в реальном времени для больших наборов данных? При разбивке / сортировке записей в памяти при каждом запросе (что я делаю сейчас, что я могу несколько оптимизировать с помощью ежечасного хрон, но это не в режиме реального времени), генерация отчетов занимает около секунды (формулы сложных дат и такой), иногда дольше.

Помимо традиционных оптимизаций (лучшая реализация даты, лучшие практики sql / nosql), где я могу найти несколько практических и проверенных статей о построении отчетов? Я могу создавать отчеты без проблем, вопрос в том, как сделать это быстро, в режиме реального времени, оптимизировано и правильно ? На самом деле ничего не нашли.

1 Ответ

1 голос
/ 03 мая 2018

Самый простой способ создания отчетов в режиме реального времени для вашего варианта использования - это использовать кэширование.

Так что в методе отчета вам нужно использовать кеш рельсов

class User < ActiveRecord::Base
  class << self
    def report
      Rails.cache.fetch('users_report', expires_in: 10.seconds) do
        result = {}
        User.find_in_batches(:include => :page_views) do |users|
          # some calculations
          # result[:users]...
          users.each do |user|
            # result[:users][:counts][:active]...
            # some more calculations
          end
        end
        result
      end
    end
  end
end

А на стороне клиента вы просто запрашиваете этот отчет с помощью пула ajax. Таким образом, создание этих отчетов не будет узким местом, поскольку их создание занимает ~ 1 секунду, и многие клиенты могут легко получить самый последний результат.

Для лучшего взаимодействия с пользователем вы можете хранить дельту между двумя отчетами и увеличивать свой отчет на стороне клиента с помощью этого прогноза дельты, например:

let nextPredictedReport = null;
let currentReport = null;

const startDrawingPredicted = () => {
  const step = 500;
  const timePassed = 0;
  setInterval(() => {
    timePassed += step;
    const predictedReport = calcDeletaReport(currentReport, nextPredictedReport, timePassed);
    drawReport(predictedReport);
  }, step);
};

setInterval(() => {
  doReportAjaxRequest().then((response) => {
    drawReport(response.report);
    currentReport = response.report;
    nextPredictedReport = response.next_report;
    startDrawingPredicted();
  });
}, 10000);

это всего лишь пример подхода, calcDeletaReport и drawReport должны быть реализованы самостоятельно + у этого решения могут быть проблемы, так как это всего лишь идея :)

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