Денормализация для рассудка или производительности?

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

    from va in VehicleActions
    join vat in VehicleActionTypes on va.VehicleActionTypeId equals vat.VehicleActionTypeId
    join ai in ActivityInvolvements on va.VehicleActionId equals ai.VehicleActionId
    join a in Agencies on va.AgencyId equals a.AgencyId
    join vd in VehicleDescriptions on ai.VehicleDescriptionId equals vd.VehicleDescriptionId
    join s in States on vd.LicensePlateStateId equals s.StateId
    where va.CreatedDate > DateTime.Now.AddHours(-DateTime.Now.Hour)
    select new {va.VehicleActionId,a.AgencyCode,vat.Description,vat.Code,
vd.LicensePlateNumber,LPNState = s.Code,va.LatestDateTime,va.CreatedDate}

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

Когда я обратился к администратору базы данных с проблемой кода состояния, и 5 таблиц объединяются. я получаю ответ, что «мы нормализованы» и «соединения выполняются быстро».

Есть ли веские аргументы в пользу денормализации? Я бы сделал это для рассудка, если бы ничего другого.

тот же запрос в T-SQL:

    SELECT VehicleAction.VehicleActionID
      , Agency.AgencyCode AS ActionAgency
      , VehicleActionType.Description
      , VehicleDescription.LicensePlateNumber
      , State.Code AS LPNState
      , VehicleAction.LatestDateTime AS ActionLatestDateTime
      , VehicleAction.CreatedDate
FROM VehicleAction INNER JOIN
     VehicleActionType ON VehicleAction.VehicleActionTypeId = VehicleActionType.VehicleActionTypeId INNER JOIN
     ActivityInvolvement ON VehicleAction.VehicleActionId = ActivityInvolvement.VehicleActionId INNER JOIN
     Agency ON VehicleAction.AgencyId = Agency.AgencyId INNER JOIN
     VehicleDescription ON ActivityInvolvement.VehicleDescriptionId = VehicleDescription.VehicleDescriptionId INNER JOIN
     State ON VehicleDescription.LicensePlateStateId = State.StateId
Where VehicleAction.CreatedDate >= floor(cast(getdate() as float))

person MarkDav.is    schedule 15.10.2009    source источник


Ответы (7)


Я не знаю, назвал бы я то, что вы хотите сделать денормализацией - это больше похоже на то, что вы просто хотите заменить искусственные внешние ключи (StateId, AgencyId) естественными внешними ключами (State Abbreviation, Agency Code). Использование полей varchar вместо целочисленных полей замедлит производительность соединения / запроса, но (а) если вам даже не нужно присоединяться к таблице большую часть времени, потому что естественный FK - это то, что вы хотите в любом случае, это не имеет большого значения и ( б) ваша база данных должна быть довольно большой / иметь высокую нагрузку, чтобы она была заметной.

Но djna прав в том, что вам нужно полное понимание текущих и будущих потребностей, прежде чем вносить подобные изменения. Вы УВЕРЕНЫ, что трехбуквенный код агентства никогда не изменится, даже через пять лет? Действительно, действительно уверены?

person Paul Abbott    schedule 15.10.2009
comment
Раньше я был большим поклонником элегантности, логики и ясности естественных внешних ключей, но они просто не стоят постоянных хлопот по обслуживанию. Поэтому вместо этого я создал элегантные инструменты для управления искусственными ключами, и все успели домой к обеду. - person overslacked; 16.10.2009

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

Но почему бы просто не создать несколько удобных представлений (для выполнения нескольких объединений), а затем использовать их для написания более простых запросов?

person ChristopheD    schedule 15.10.2009
comment
Идея небольших, простых, многоразовых функций должна применяться ко всему правильному коду, когда это возможно. Я много пользуюсь табличными функциями и представлениями для подобных вещей. И, как бонус, отчетность становится намного проще. - person overslacked; 16.10.2009

Остерегайтесь желать привести вещи в соответствие с вашими текущими идиомами. Прямо сейчас незнакомый код кажется неприятным и мешающим вашему пониманию. Возможно, со временем вы акклиматизируетесь.

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

person djna    schedule 15.10.2009
comment
+1 за указание на то, что разработчики со временем растут. Я думаю, что в этой ситуации лучше научиться иметь дело с гипер-нормализованными данными и корректировать, а не подгонять данные под то, что нам удобно. - person David; 16.10.2009

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

Работа с гипернормализованными данными

Мое личное мнение о нормализации - нормализовать как можно больше, но денормализовать только для производительности. И даже денормализации производительности следует избегать. Я бы пошел по пути профилирования, установки правильных индексов и т. Д., Прежде чем денормализовал.

Здравомыслие ... Это переоценено. Особенно в нашей профессии.

person David    schedule 15.10.2009
comment
+1 за саундбайт здравомыслия. Не возражаете, если я процитирую вас при случае? ;-) - person sleske; 16.10.2009

Ну что с производительностью? Если с производительностью все в порядке, просто сделайте пять таблиц JOIN в представлении и для разумности выберите SELECT из представления, когда вам понадобятся данные.

Аббревиатуры состояний - это один из тех случаев, когда я думаю, что значимые ключи - это нормально. Для очень простых таблиц поиска с ограниченным количеством строк и где я полностью контролирую данные (то есть они не заполняются из какого-либо внешнего источника) я иногда создаю значимые четырех- или пятисимвольные ключи, чтобы значение ключа могло прокси для полностью описательного значения поиска в некоторых запросах.

person Larry Lustig    schedule 16.10.2009

Создайте представление (или встроенную функцию с табличным значением, чтобы получить параметризацию). В любом случае я обычно помещаю весь свой код в SP (некоторый сгенерированный код), независимо от того, используют ли они представления или нет, и в этом случае вы почти всегда пишете соединение только один раз.

person Cade Roux    schedule 16.10.2009

Аргумент (для этой «нормализации») о том, что трехбуквенные коды могут измениться, не очень убедителен без плана того, что вы будете делать, если коды действительно изменятся, и того, как ваш сценарий с искусственным ключом решит эту проблему лучше, чем использование коды как ключи. Если вы не реализовали полностью временную схему (что ужасно сложно сделать и не предлагается в вашем примере), мне не очевидно, какая польза от вашей нормализации для вас вообще. Теперь, если вы работаете с агентствами из разных источников и стандартов, которые могут иметь противоречащие друг другу кодовые названия, или если «штат» в конечном итоге может означать двухбуквенный код штата, провинции, департамента, кантона или эстадо, это другое дело. Затем вам понадобятся ваши собственные ключи или вам понадобится ключ из двух столбцов с дополнительной информацией, чем этот код.

person Steve Kass    schedule 16.10.2009