Вопрос базы данных с отношением один ко многим со значением по умолчанию - PullRequest
1 голос
/ 22 марта 2019

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

Мой вопрос : у пользователя может быть много адресов, но он может пометить только один в качестве основного (для целей доставки). Лучше добавить внешний ключ для пользователя с именем «main_address», который ссылается на один из его адресов, или добавить столбец в таблицу адресов с именем «is_main» (0 по умолчанию для всех адресов и 1 для основного адреса) ? Лучше я имею в виду скорость и объем хранения:)

РЕДАКТИРОВАТЬ: Как предложено, я добавил внешний ключ для пользователя, но это проблематично. Если пользователя и адреса еще нет в базе данных, это приводит к циклической зависимости: пользователь не может быть добавлен без адреса, а адрес не может быть добавлен без пользователя. Спасибо всем!

1 Ответ

1 голос
/ 22 марта 2019

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

Уникальность встроенного в внешний ключ дизайна. При использовании конструкции is_main простейшим предупреждением является создание поля 1 или нуля (вместо 1 или 0) и добавление составного уникального ключа (user_id, is_main); и затем, чтобы изменить значение по умолчанию, вы должны были бы обнулить старое значение по умолчанию, прежде чем установить новое в 1.

Поле внешнего ключа занимает примерно 4 байта (при условии int pk для адресов и игнорирования обнуляемости); is_main занимает по крайней мере 1 байт для каждого адреса, который может иметь пользователь ... если есть другие битовые поля, он может быть меньше, но проблемы с пространством действительно тривиальны.

Чтобы получить пользователя с адресом по умолчанию:

SELECT * 
FROM user AS u 
LEFT JOIN address AS a 
   ON u.main_address_id = a.address_id 
WHERE u.user_id = ?
;

против

SELECT * 
FROM users AS u 
LEFT JOIN address AS a 
   ON u.user_id = a.user_id 
   AND a.is_main = 1 
WHERE u.user_id = ?
;

... что AND is_main = 1 может показаться тривиальной вещью, и во многих случаях это будет так, но в более сложном запросе это такая вещь, которая может означать, что не нужно брать индекс.

Тем не менее, положительная сторона дизайна is_main: если у вас уже есть user_id, но не main_address_id, вы можете получить информацию об основном адресе простым выбором (без объединения) только из таблицы адресов.

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