Нужно ли иметь 1 или 2 таблицы для личных адресов пользователей и адресов групп пользователей? - PullRequest
2 голосов
/ 21 июня 2011

Если у меня есть пользователи, а также группы пользователей (например, местная астрономическая группа / клуб), и я хочу, чтобы у обоих были отношения один-ко-многим с уличными адресами, могу ли я иметь только одну таблицу адресов и два фк такчто мне не нужно дублировать схему таблицы?или лучше всего иметь две отдельные таблицы: user_addresses и user_group_addresses?Цените ваш вклад и время, спасибо!

Ответы [ 4 ]

5 голосов
/ 21 июня 2011

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

3 голосов
/ 21 июня 2011

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

Например, адрес должен ссылаться на один объект, поэтому концептуально столбец является обязательным и должен иметь значение NOT NULL.Но вы не можете сделать оба столбца НЕ ПУСТО (NULL), потому что один из них не относится к данному адресу.Поэтому они должны быть обнуляемыми.И тогда у вас должен быть какой-то другой способ не допустить, чтобы оба были NULL, а также чтобы оба не были NULL.MySQL не поддерживает ограничения CHECK, поэтому вы можете написать триггер или написать собственный код приложения для обеспечения соблюдения этого правила.

А как насчет создания одной таблицы адресов, но с обратной связью?То есть таблицы «Пользователи» и «Группы» содержат ссылку на внешний ключ к таблице «Адреса», а не наоборот.

Другое решение состоит в том, чтобы и пользователи, и группы зависели от общего суперпользователя, назовите его «Addressables "или что-то.Как интерфейс или абстрактный класс в ОО-дизайне.Тогда ваши адреса также могут иметь внешний ключ для Addressables.См. Примеры в других вопросов, на которые я ответил на эту тему .

Я также более подробно рассмотрю эту проблему в своей книге Антипаттерны SQL, как избежать ошибок в программировании баз данных , в главе «Полиморфные ассоциации».

2 голосов
/ 21 июня 2011

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

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

Например, нам нужны данные из адресов пользователей:

SELECT * FROM user_address WHERE <other conditions>; // The two-table strategy

/**
 * The one-table strategy
 */
SELECT * FROM all_addresses
WHERE user_id IS NOT NULL
    AND <other conditions>;

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

В стратегии с одной таблицей, возможно, условие "НЕ НУЛЬ"не будет оптимизирован, даже если в этом столбце есть индекс (зависит от систем баз данных).Объединение - это еще один способ распознавания адресов пользователей в стратегии «за одним столом», но при этом требуется больше усилий, чем в другой стратегии.

Однако стратегия «за одним столом» имеет свои преимущества в производительности.Если нам нужно собрать все адреса (независимо от пользователей или групп) и этот тип операций является узким местом производительности системы, вы можете рассмотреть возможность использования стратегии с одной таблицей.

2 голосов
/ 21 июня 2011

Гораздо лучше иметь 1 адресную таблицу, если нет особых потребностей, которые один тип адреса имеет по сравнению с другим.Это намного проще в обслуживании, а также позволяет добавить функциональность.Например, если ваша местная астрономическая группа решает, что они хотят где-то иметь «события», тогда вы просто создаете таблицу событий и ссылаетесь на таблицу адресов, и вы готовы пойти.Если вы их разложите, то каждый раз, когда у вас будет новый «объект» с адресом, вам придется создавать новую таблицу.

Надеюсь, это поможет.

Что касается вашего комментария: я бы поместил ссылку в отдельную справочную таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...