таблица пользователя веб-приложения первичный ключ: суррогатный ключ vs имя пользователя vs email vs идентификатор клиента
Я пытаюсь создать веб-приложение электронной коммерции в MySQL, и у меня возникают проблемы с выбором правильных первичных ключей для таблицы пользователя. приведенный пример является лишь примером для иллюстрации.
таблица пользователя имеет следующее определение
CREATE TABLE IF NOT EXISTS `mydb`.`user` (
`id` INT NOT NULL ,
`username` VARCHAR(25) NOT NULL ,
`email` VARCHAR(25) NOT NULL ,
`external_customer_id` INT NOT NULL ,
`subscription_end_date` DATETIME NULL ,
`column_1` VARCHAR(45) NULL ,
`column_2` VARCHAR(45) NULL ,
`colum_3` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `username_UNIQUE` (`username` ASC) ,
UNIQUE INDEX `email_UNIQUE` (`email` ASC) ,
UNIQUE INDEX `customer_id_UNIQUE` (`external_customer_id` ASC) )
ENGINE = InnoDB
я сталкиваюсь со следующими проблемами со столбцами кандидатов первичного ключа:
столбец Id
плюсы
- нет бизнес-значения (стабильный первичный ключ)
- быстрее присоединяется к таблице
- индекс поплотнее
минусы
- не "естественный" ключ
- все таблицы атрибутов должны быть объединены с пользовательской таблицей" master", поэтому невозможны прямые запросы без присоединения
- вызывает меньше "естественных" SQL-запросов
- утечки информация: пользователь может определить количество зарегистрированных пользователей, если начальное значение равно 0 (изменение начального значения) ii) пользователь регистрирует профиль как user_A в time_X и некоторое время спустя как user_B в time_Y легко сможет вычислить количество зарегистрированных пользователей за период времени ((Id для user_B) - (Id для user_A)/(time_Y - time_X))
почта колонка
плюсы
- нет
минусы
- пользователь должен иметь возможность изменить адрес электронной почты. Не подходит для первичного ключа
столбец username
плюсы
- "естественный" первичный ключ
- меньше соединений таблиц
- проще и более "естественные" запросы
минусы
- столбец varchar медленнее при соединении таблиц
- индекс столбца varchar менее компактен, чем индекс столбца int
- очень сложно изменить имя пользователя, так как внешние ключи зависят от значения. Решение: "синхронизация" всех внешних ключей в приложении или не позволяя пользователю изменять имя пользователя .например, пользователь должен удалить профиль a register новый
столбец external_customer
плюсы
-
может использоваться как внешняя ссылка для клиента и не содержит никакой информации (возможно, вместо этого можно использовать не редактируемое имя пользователя? )
минусы
может утечка информации, если она является автоматической инкрементной (если это возможно)
- проблематично генерировать значение unqiue, если авто инкрементный суррогатный id уже используется, так как MySQL innodb engine не содержит несколько столбцов auto_increment в одной таблице
какова обычная практика при выборе первичного ключа таблицы пользователя масштабируемое веб-приложение электронной коммерции? все отзывы оценили
3 ответов
Мне нечего сказать о некоторых ваших анализах. Если я сократил некоторые из ваших " за " или "против", это только означает, что я не думаю, что у меня есть что-то полезное добавить.
столбец Id
плюсы
- нет бизнес-значения (стабильный первичный ключ)
- быстрее присоединяется к таблице
- индекс поплотнее
во-первых, любой столбец или набор столбцов, объявленных NOT NULL UNIQUE имеет все свойства первичного ключа. Вы можете использовать любой из них в качестве цели для ссылки на внешний ключ, что и есть все это действительно о программе.
в вашем случае ваша структура позволяет 4 столбцам быть целями ссылки внешнего ключа: id, username, email и external_customer_id. Вы не должны использовать тот же самый все время. Возможно, имеет смысл использовать id для 90% ваших ссылок FK и электронную почту для 10% их.
стабильность не имеет ничего общего с тем, имеет ли столбец бизнес-значение. Стабильность зависит от того, как часто и при каких обстоятельствах ценность может меняться. "Стабильный "не означает" неизменяемый", если вы не используете Oracle. (Oracle не может делать каскад обновлений.)
в зависимости от структуры таблицы и индексации, естественный ключ может работать быстрее. Естественные ключи делают некоторые соединения ненужными. Я провел тесты, прежде чем создать нашу производственную базу данных. Это вероятно, пройдут десятилетия, прежде чем мы достигнем точки, когда соединения по ID-номерам превзойдут меньшее количество соединений и естественных ключей. Я писал об этих тестах либо на SO, либо на DBA.
У вас есть три других уникальных индексов. (хороший для вас. Я думаю, что по крайней мере 90% людей, которые строят базу данных, не понимают этого.) Так что дело не только в том, что индекс на идентификационном номере более компактный, чем любой из этих трех; это также дополнительные. (В этом таблица.)
столбец электронной почты
плюсы
- нет
адрес электронной почты можно считать стабильным и уникальным. Вы не можете запретить людям обмениваться адресами электронной почты, независимо от того, является ли это целью ссылки на внешний ключ.
но адреса электронной почты могут быть "потеряны". В США большинство студентов университетов теряют свои *.адреса электронной почты edu с годом или около того об окончании школы. Если ваш адрес электронной почты приходит через домен, за который вы платите, и вы перестаете платить, адрес электронной почты уходит. Я предполагаю, что это возможно для адреса электронной почты, как те, которые будут предоставлены новым пользователям. Создает ли это невыносимое бремя, зависит от приложения.
минусы
- пользователь должен иметь возможность изменить адрес электронной почты. Не подходит для первичного ключа
все значения в базу данных SQL можно изменить. Это непригодно, только если ваша среда не позволяет вашей СУБД своевременно выполнять каскадное объявление ON UPDATE. Мое окружение знает. (Но я запускаю PostgreSQL на приличном, неразделенном оборудовании.) YMMV.
столбец username
плюсы
- "естественный" первичный ключ
- меньше соединений таблиц
- более простые и более" естественные " запросы
меньше соединений является важным моментом. Я был на консультационных концертах, где я видел бессмысленное использование ID-номеров, заставляющих людей писать запросы с 40 + соединениями. Рациональное использование естественных ключей исключило до 75% из них.
Не важно всегда использовать суррогатные ключи в качестве цели для внешних ключей (если только Oracle) или всегда использовать естественные ключи в качестве цели. Важно подумать.
минусы
- столбец varchar медленнее при соединении таблиц
- индекс столбца varchar менее компактен, чем индекс столбца int
вы не можете сказать, что присоединение к varchar () медленнее без квалификации этого требования. Дело в том, что, хотя большинство присоединяется к varchar () are медленнее, чем соединения на идентификационные номера, они не обязательно так медленно, что вы не можете использовать их. Если запрос принимает 4ms с id-номерами и 6ms с varchar (), я не думаю, что это хорошая причина дисквалифицировать varchar (). Кроме того, использование естественного ключа устранит много соединений, поэтому общий ответ системы может быть быстрее. (При прочих равных условиях 40 4ms присоединяется, будет хуже 10 6ms присоединяется.)
Я не могу вспомнить ни одного случая в моей карьере базы данных (25+ лет), когда ширина индекса была решающим фактором при выборе цели для внешнего ключа.
столбец external_customer
плюсы
- может использоваться как внешняя ссылка для клиента и не содержит никакой информации (возможно, вместо этого можно использовать не редактируемое имя пользователя? )
на самом деле существует несколько систем, которые позволяют мне изменить свое имя пользователя. Большинство позволит мне изменить мое реальное имя (я думаю), но не мое имя. Я думаю, что нередактируемом имя пользователя является полностью обоснованным.
В общем случае веб-приложения стараются держать свою схему базы данных подальше от клиента, включая первичные ключи. Я думаю, вы объединяете свой дизайн схемы с методами аутентификации - ничто не мешает вам разрешать пользователям входить в систему со своим адресом электронной почты, даже если ваш дизайн базы данных использует целое число для их уникальной идентификации.
всякий раз, когда я разрабатывал такие системы, я использовал столбец ID - integer или GUID для первичного ключа. Это быстро, не меняется из-за надоедливых реальных жизненных ситуаций и является знакомой идиомой для разработчиков.
затем я разработал лучшую схему аутентификации для приложения в руке-большинство людей ожидают входа в систему со своим адресом электронной почты в эти дни, поэтому я бы придерживался этого. Конечно, вы также можете позволить им войти в систему со своими учетными записями Facebook, Twitter или Google. Но это не имеет никакого отношения к моему первичному ключу...
Я думаю, что с столбцом username у вас также есть эти минусы:
- пользователь должен иметь возможность изменить имя пользователя. Не подходит для первичного ключа.
поэтому по той же причине, по которой вы не будете использовать электронную почту, я не буду использовать имя пользователя. Для меня integer id внутреннего пользователя-лучший подход.