5

Я использую Rails и MySQL и задаю вопрос об эффективности на основе подсчета строк.Сохраняет ли количество записей базы данных избыточным?

У меня есть модель Project, которая has_many :donations.

Я хочу подсчитать количество уникальных доноров для проекта.

Есть ли поле в таблице projects с именем num_donors и приращивание его при создании нового донора?

Или что-то вроде @num_donors = Donor.count(:select => 'DISTINCT user_id') будет аналогичным или же с точки зрения эффективности благодаря оптимизации базы данных? Будет ли это требовать от меня создания индексов для user_id и любых других полей, которые я хочу сосчитать?

Выполняется ли тот же ответ для суммирования общей суммы пожертвования?

ответ

10

Чтобы ответить на вопрос заголовка. Да, это избыточно, но нужно ли вам это делать, зависит от вашей ситуации.

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

В большинстве случаев вам не придется прибегать к этому, и не следует.

Если необходимо хранить расчетные значения, выполните следующие действия:

  • Не поддерживать его в актуальном состоянии приращением его. Пересчитайте счет/общее количество всех данных каждый раз, когда вы его обновляете.
  • Если у вас нет много обновлений, введите код в триггер обновления до , чтобы сохранить счет/итоги в актуальном состоянии.
  • Проблема с резервированием в базах данных заключается в том, что когда числа не согласны, то вы не уверены, что это авторитетный. Добавьте к документу примечание о том, что источник является достоверным источником, если они не согласны и могут быть перезаписаны.
7

Хотя это зависит от размера вашей базы данных, это те виды операций, в которых специализируются базы данных, поэтому они должны быть быстрыми. Вероятно, это случай преждевременной оптимизации - вы должны начать с того, что не сохраняете итоговые значения, тем самым упрощая их - и при необходимости оптимизируйте позже.

4

ответов Питера и JohnFx являются звуком, то, что вы предлагаете это denormalization вашей схемы базы данных, которая может улучшить производительность операций чтения, но в ущербе записи в то время как дополнительно положить ответственность на разработчике (или дополнительного СУБД Clevers) для предотвращения несоответствий в вашем наборе данных.

ActiveRecord имеет встроенные функции для автоматического управления счетами на has_many отношениях. Проверьте это Railscast on counter caches.

5

Помните принцип «Человек с одним часом всегда знает время. Человек с двумя часами никогда не будет уверен.« Я бы только сохранил производный номер, если:

Проблемы с производительностью мешают вам получать производные числа, когда они вам нужны (что не должно быть проблемой в этом случае, поскольку ответ, скорее всего, будет доступен из индексов)

или

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

+0

Любите максиму - не слышали ее раньше. Будем держать это в виду :) – nfm

3

Знаете ли вы что простой флаг делает магию ActiveRecord?

class ThingOwner 

# it has a column like 
# t.integer things_count, :default => 0 

has_many :things, :counter_cache => true 

end 

Что касается вопроса - да, уверен, что это излишним, я хотел бы добавить такой счетчик, если и только если доля things.count «s времени слишком велик.

В противном случае это преждевременная оптимизация.