Сохраняется ли избыточное количество записей в базе данных? - PullRequest
5 голосов
/ 03 октября 2009

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

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

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

Имеет ли в таблице projects поле с именем num_donors и увеличивает его при создании нового донора - хорошая идея?

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

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

Ответы [ 5 ]

10 голосов
/ 03 октября 2009

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

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

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

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

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

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

5 голосов
/ 03 октября 2009

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

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

или

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

4 голосов
/ 03 октября 2009

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

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

3 голосов
/ 03 октября 2009

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

class ThingOwner

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

has_many :things, :counter_cache => true

end

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

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

...