В какой базе данных вы должны хранить производные данные? - PullRequest
10 голосов
/ 08 ноября 2010

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

Например, скажем, у вас есть Пользователи, которые получают Upvotes за свои Вопросы.Вы отображаете репутацию пользователя в его профиле.Когда Пользователь получает Голосование с повышением рейтинга, следует ли повысить его репутацию или рассчитать его при извлечении его профиля:

SELECT User.id, COUNT(*) AS reputation FROM User
LEFT JOIN Question
  ON Question.User_id = User.id
LEFT JOIN Upvote
  ON Upvote.Question_id = Question.id
GROUP BY User.id

Насколько интенсивно требуется процессор, чтобы запросить репутацию пользователя должен быть раньшеСтоит ли отслеживать его постепенно с помощью своего собственного столбца?

Чтобы продолжить наш пример, предположим, что вес Upvote зависит от того, сколько Upvotes (не сколько репутации) имеет пользователь, который его разыграл.Запрос на получение их репутации внезапно взрывается:

SELECT
  User.id AS User_id,
  SUM(UpvoteWeight.weight) AS reputation
FROM User
LEFT JOIN Question
  ON User.id = Question.User_id
LEFT JOIN (
  SELECT
    Upvote.Question_id,
    COUNT(Upvote2.id)+1 AS weight
  FROM Upvote
  LEFT JOIN User
    ON Upvote.User_id = User.id
  LEFT JOIN Question
    ON User.id = Question.User_id
  LEFT JOIN Upvote AS Upvote2
    ON
      Question.id = Upvote2.Question_id
      AND Upvote2.date < Upvote.date
  GROUP BY Upvote.id
) AS UpvoteWeight ON Question.id = UpvoteWeight.Question_id
GROUP BY User.id

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

Ответы [ 3 ]

5 голосов
/ 08 ноября 2010

Насколько интенсивным должен быть процессор, чтобы запросить репутацию пользователя, прежде чем стоило бы постепенно отслеживать его с помощью собственного столбца?

На самом деле есть два вопросаздесь под видом одного: (1) это изменение улучшит производительность и (2) будет ли улучшение производительности стоить усилий?


Что касается улучшения производительности, это в основном стандартАнализ плюсов / минусов.

Преимущества нормализации в основном двояки:

  • Упрощенная целостность данных

  • Нет проблемс пересчетом (например, если базовые данные изменяются, производный столбец необходимо пересчитать).

Если вы покрываете целостность данных с помощью надежно реализованного решения (например, триггер,Изменения данных только для Sstored-proc с отзывом прямых разрешений на изменение таблиц и т. Д.), А затем это становится прямым вычислением того, стоит лиизменение данных требует повторного расчета производных данных по сравнению с повторным вычислением полученных данных каждый раз.(ПРИМЕЧАНИЕ. Другой подход к сохранению целостности данных заключается в том, чтобы принудительно пересчитывать производные данные по расписанию, когда эти данные могут быть неточными с некоторым временным отклонением. StackExchange использует этот подход с некоторыми из своих чисел).

В типичном сценарии (гораздо больше поиска данных и гораздо меньше изменений в базовых данных) математика довольно явно искажается в пользу сохранения в таблице денормализованных производных данных.

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


Теперь мы находимся в гораздо болееважный вопрос: Стоит ли улучшение производительности?

Обратите внимание, что, как и во ВСЕХ оптимизациях, самый большой вопрос - "стоит ли вообще оптимизация?", икак таковой, является предметом двух основных соображений:

  1. Измерение точной разницы производительности и в целом профилирования.

  2. Контекст этой конкретной оптимизации в целомизображение вашей системы.

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

1 голос
/ 08 ноября 2010

На самом деле нет однозначного ответа, потому что это зависит от множества факторов, таких как объем сайта и то, как часто вы отображаете репутацию (то есть только на странице своего профиля или рядом с КАЖДЫМ экземпляром своего имени пользователя, везде),Единственный реальный ответ - «когда он становится слишком медленным»;другими словами, вам, вероятно, потребуется протестировать оба сценария и получить некоторые реальные характеристики производительности.

Лично я бы денормализовал в этой конкретной ситуации и имел бы либо триггер вставки в таблицу upvote, либо периодическое обновлениезапрос, который обновляет денромализованный столбец репутации.Неужели действительно будет конец света, если кто-то из представителей скажет "204" вместо "205", пока страница не обновится?

0 голосов
/ 02 декабря 2010

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

...