Это хороший способ для моделирования адресной информации в реляционной базе данных? - PullRequest
26 голосов
/ 21 ноября 2008

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

Вариант 1 Поместите все столбцы адреса в качестве атрибутов в различные таблицы. Скопируйте детали от поставщика в ПО по мере его создания. Потенциально хранить несколько копий

Вариант 2 Создайте отдельную таблицу адресов. Получить внешний ключ от поставщика и таблицы заказов на покупку к таблице адресов. Разрешите вставлять и удалять только в адресной таблице, поскольку обновления могут измениться больше, чем вы предполагаете. Тогда у меня была бы какая-то запланированная задача, которая удаляет все строки из таблицы адресов, на которые больше нет ссылок, так что неиспользуемые строки не остались. Возможно, также есть уникальное ограничение на все столбцы не-pk в таблице адресов, чтобы также останавливать дубликаты.

Я склоняюсь к варианту 2. Есть ли лучший способ?

РЕДАКТИРОВАТЬ: я должен сохранить адрес в заказе на покупку, как это было при отправке. Кроме того, это немного сложнее, чем я предложил, так как это может быть адрес доставки и адрес выставления счета (есть также куча других таблиц с адресной информацией).

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

Ответы [ 7 ]

26 голосов
/ 21 ноября 2008

Я фактически использую это как один из моих вопросов интервью. Вот хорошее место для начала:

Addresses
---------
AddressId (PK)
Street1
... (etc)

и

AddressTypes
------------
AddressTypeId
AddressTypeName

и

UserAddresses (substitute "Company", "Account", whatever for Users)
-------------
UserId
AddressTypeId
AddressId

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

Один из несколько противоречивых советов для потенциально большой базы данных: добавьте «первичный» адрес непосредственно к вашим сущностям (в данном случае в таблице «Пользователи») вместе с полем «HasMoreAddresses». Это выглядит странно по сравнению с простым использованием приведенного выше дизайна, но может упростить кодирование для типичных случаев использования, а денормализация может существенно повлиять на производительность.

6 голосов
/ 21 ноября 2008

Вариант 2, без сомнения.

Некоторые важные вещи, которые следует иметь в виду: это важный аспект дизайна, который указывает пользователям, когда адреса связаны друг с другом. То есть корпоративный адрес совпадает с адресом доставки; если они хотят изменить адрес доставки, они также хотят изменить корпоративный адрес или они хотят указать новую загрузочную док-станцию? Такие вещи, а также возможность предоставлять пользователям эту информацию и изменять вещи с такой степенью детализации, ОЧЕНЬ важны. Это важно и в отношении обновлений; дать пользователю возможность «разделить» записи. Не то чтобы этот вид пользовательского интерфейса прост в разработке; на самом деле, это сука. Но это действительно важно сделать; все, что меньше, почти наверняка заставит ваших пользователей очень расстроиться и раздражиться.

Также; Я настоятельно рекомендую хранить старые данные адреса; не запускайте процесс, чтобы очистить его. Если у вас ОЧЕНЬ занятая база данных, программное обеспечение вашей базы данных сможет обрабатывать избыточные данные. В самом деле. Одна распространенная ошибка, которую я вижу в отношении баз данных, заключается в попытке переоптимизации; вы действительно хотите оптимизировать свои запросы, но не хотите оптимизировать свои неиспользуемые данные. (Опять же, если ваша активность базы данных ОЧЕНЬ ВЫСОКАЯ, вам может потребоваться, чтобы что-то для этого было сделано, но почти наверняка ваша база данных будет работать хорошо, сохраняя избыточные данные в таблицах.) В большинстве случаев это на самом деле более выгодно просто позволить вашей базе данных расти, чем пытаться оптимизировать ее. (Удаление спорадических данных из ваших таблиц не приведет к значительному уменьшению размера вашей базы данных, и когда это произойдет ... ну, переиндексация, которая вызывает это, может быть гигантской утечкой в ​​базе данных.)

3 голосов
/ 21 ноября 2008

Я думаю, что согласен с JohnFx ..

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

Лучшие поля будут:

  • Имя / Компания
  • Адрес (многострочная текстовая область)
  • Страна

Это должно быть довольно глобально, если почтовой системе США требуются почтовые индексы в определенном формате, а затем включите это, но сделайте его необязательным, если США не выбраны в качестве страны. Все знают, как отформатировать адрес в своей стране, так что, пока вы сохраняете разрывы строк, все должно быть в порядке ...

1 голос
/ 21 ноября 2008

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

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

1 голос
/ 21 ноября 2008

Хотите ли вы вести исторический учет того, какой адрес изначально был в заказе на покупку?

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

Кстати: верным признаком плохого дизайна БД является необходимость автоматизированной работы для поддержания данных в чистоте или в синхронизации. Вариант 2, скорее всего, плохая идея по этой мере

0 голосов
/ 03 февраля 2009

Я видел, как каждая система, использующая вариант 1, сталкивалась с проблемами качества данных. Через 5 лет 30% всех адресов перестанут быть текущими.

0 голосов
/ 21 ноября 2008

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

Адресная таблица - хорошая идея. Установите для него уникальное ограничение, чтобы один и тот же объект не мог иметь повторяющиеся адреса. Вы можете получить их, так как пользователи могут добавить другой вместо того, чтобы искать их, и если они пишут вещи немного по-другому (St. вместо Street), уникальное ограничение не помешает этому. Скопируйте данные во время создания заказа в заказ. Это один случай, когда вам нужно несколько записей, потому что вам нужна историческая запись того, что вы отправили куда. Только разрешать вставки и удаления в таблицу для меня не имеет смысла, так как они не безопаснее обновлений и требуют больше работы для базы данных. Обновление выполняется за один вызов базы данных. Если адрес меняется в вашей идее, вы должны сначала удалить старый адрес, а затем вставить новый. Не только больше обращений к базе данных, но и в два раза больше шансов сделать ошибку кода.

...