база данных: куда поместить внешние ключи в «имеет» отношение? - PullRequest
1 голос
/ 03 апреля 2012

У меня есть база данных с двумя типами пользователей.Что-то вроде:

User:
    name: String
    email: String

PowerUser
    address: String
    paypalAcct: String

, где каждый пользователь - User, но люди, которые подписались на расширенные услуги и т. Д., Также имеют PowerUser, прикрепленный к их учетной записи.Я хотел разделить User и PowerUser, потому что я думал, что было бы неплохо повторно использовать таблицу User для людей, которые уже стали PowerUser s, потому что у них должны быть все обычные вещи User sиметь.

Правильно ли это сделать, или я должен добавить поля User в таблицу PowerUser и просто поработать с этим?

Если это правильнодействительно ли User должен иметь внешний ключ, который указывает на PowerUser, или PowerUser должен иметь внешний ключ, который указывает на User?Я думаю, это зависит от порядка доступа к этим вещам?В этом случае я почти всегда буду идти от User и проверять, есть ли соответствующий PowerUser, а не наоборот.

Если я введу внешний ключ в User s, тогда большое количество пользователей будет иметь нулевой внешний ключ.Если я добавлю внешний ключ в PowerUsers, то все они будут заполнены, но для перехода от User s к PowerUser s потребуется перебор всей таблицы PowerUser s.Что предпочтительнее?

Ответы [ 3 ]

2 голосов
/ 03 апреля 2012

Очевидный ответ - добавить внешний ключ в зависимую таблицу.Пользователям не нужна информация о PowerUser.

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

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

select 
    a.id, a.email, a.name, a.email, b.address, b.paypalacct 
from 
    users a 
    left outer join powerusers b on a.id = b.id

Если вы хотите получить список только опытных пользователей, тогда вы используете внутреннее соединение .

select
    a.id, a.email, a.name, a.email, b.address, b.paypalacct
from 
    users a 
    inner join powerusers b on a.id = b.id
1 голос
/ 03 апреля 2012

Предпочтительным является легко индексируемый суррогатный ключ (как это обычно бывает с данными учетной записи пользователя):

User:
    id            INTEGER NOT NULL PRIMARY KEY
    name          VARCHAR
    email         VARCHAR

PowerUser:
    id            INTEGER NOT NULL PRIMARY KEY REFERENCES(User.id)
    ...

Технически вы также можете использовать имя пользователя, но это может привести к серьезным проблемам при измененииимя пользователя, и рано или поздно это встречается почти в каждой пользовательской базе данных.Индекс PRIMARY KEY делает поиск достаточно быстрым, поэтому нет реальной потери производительности.

1 голос
/ 03 апреля 2012

Вы почти отвечаете себе:

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

Что касается FK, если вы добавите FK в PowerUser, у вас будет ненулевой столбец, который может быть первичным ключом в этой второй таблице. Так что найти запись PowerUser для пользователя очень быстро.

...