Во многих проектах реляционных баз данных есть поля, на которые ссылаются другие таблицы.
Например, рассмотрим пользовательскую таблицу с уникальным именем пользователя и вторую таблицу, в которой хранятся адресные данные.
Один из возможных вариантов, который я бы сказал, это общий подход, потому что я наблюдал в большинстве программ, это использовать идентификаторы автоинкремента:
Table users
===========
userId int primary auto_increment
userName varchar unique
Table adressdata
==========
userId int references users.userId
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userId,adress_type))
Вот как я это делал и как я видел это в большинстве случаев.
Другой способ будет:
Table users
===========
userName varchar primary
Table adressdata
==========
userName varchar references users.userName
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userName,adress_type))
Здесь мы храним полное имя пользователя также в таблице адресных данных.
Для меня это имеет следующие преимущества:
Вы можете выбрать имя пользователя прямо из таблицы без необходимости присоединять его к другой таблице. В этом примере это с точки зрения приложения, вероятно, не так актуально, но это только пример.
Возможно, будет проще масштабировать базу данных в среде репликации мастер-мастер, потому что нет конфликтов auto_increment.
Но также и недостатки:
- Требования к пространству для индекса и данных (но более уместным будет индекс) в поле во второй таблице выше.
- Изменение имени пользователя должно распространиться на все таблицы, что требует больше ресурсов, чем просто изменение его в одной таблице, и оставить идентификаторы без изменений.
На мой взгляд, гораздо проще работать с текстовыми полями и не использовать идентификаторы приращения, а компромиссы минимальны и в большинстве приложений не актуальны.
Конечно, некоторые объекты идентифицируются с возрастающим числом по своей природе (например, сообщения форума должны получать увеличивающийся идентификатор, потому что, вероятно, нет другого уникального поля, такого как title или около того).
Но прежде чем я начну разрабатывать макеты своей базы данных совершенно другим способом, я хотел бы знать, есть ли вещи, о которых я не думал.
Есть ли лучшие практики?
Есть ли плюсы / минусы, о которых я не думал, и эффект от которых может возникнуть в более поздний момент времени?
Как вы лично проектируете базы данных относительно вышеперечисленных пунктов и почему?
Я буду публиковать из моего опыта, который, вероятно, будет сильно отличаться от того, что могут предложить различные администраторы баз данных. Я в основном ориентируюсь на сочетание производительности и удобства обслуживания при проектировании баз данных для различных проектов.
Я бы никогда не использовал естественный ключ для первичного ключа. Особенно если я использую MySQL / InnoDB. Я до сих пор не видел никакой пользы от использования естественного ключа, обычно я вижу влияние на производительность, если ничего. Я выделил «никогда, никогда» только потому, что естественные ключи использовали для повышения производительности моих проектов. Суррогат (целое число) всегда был лучшим выбором. Некоторые могут не согласиться, но мы живем в мире, где производительность играет определенную роль в теории.
Когда дело доходит до СОЕДИНЕНИЙ, я не пытаюсь избежать их любой ценой, но я стремлюсь оптимизировать их. Я стараюсь максимально злоупотреблять кластерным индексом InnoDB (первичным ключом). Если JOINs выполняются через PK, то они очень быстрые. Я также склонен избегать ФК, где они не имеют смысла. Честно говоря, меня не очень заботит целостность данных, когда речь идет о связывании пользователей и их адресной информации. Я бы применил это при связывании счетов с элементами для пользователей. Чрезмерное использование FKs - это излишнее убийство и кошмар, который нужно поддерживать после того, как вы на него ссылаетесь, думая, что это отличный дизайн - поддерживать отношения повсюду. В какой-то момент все должно измениться, и когда MySQL начинает постоянно жаловаться с ошибкой 150, вы просто хотите вернуться домой.
Вы также упомянули репликацию и избежание конфликтов из-за характера auto_increments. У меня был проект, где у нас было количество баз данных, хранящих информацию о продажах продуктов, количество баз данных было переменным. Каждый день базы данных копировались в одну «основную» базу данных, которую мы использовали для запуска отчетов. Я избежал коллизий PK, создав составной первичный ключ из части auto_increment и другой части INT, которая обозначала место, откуда пришла запись. Таким образом, я мог отследить, откуда взялись вещи, и ничего не потерял (продукты имели одинаковый идентификатор, изменился только идентификатор местоположения).
источник