2010-03-27 1 views
3

Я начинаю разрабатывать приложение с использованием MySQL, и хотя я разработал приложения перед использованием баз данных, я обычно перешел к методу incrementing id. На днях я где-то читал проводку и видел, что кого-то выбрали для этого, потому что неправильно «нормализует базу данных». Я не большой человек базы данных, но я хотел убедиться, что я делаю это правильно.MySQL - Каков правильный метод первичного ключа

Любые идеи, помощь/руководство?

ответ

5

Существуют два основных метода выборе primary key:

  • Выбор первичного ключа из существующих natural candidate keys.
  • Создание surrogate key и установка его в качестве первичного ключа. В отличие от естественного ключа, суррогатный ключ не получается из данных приложения. Это тип ключа, который у вас был с помощью метода автоматического увеличения.

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

Надеюсь, это послужит кратким введением, так что вы сможете продолжить изучение своих первичных ключей.

+0

Спасибо за ответ и ссылки. Мои усилия в основном были сосредоточены на настольных и веб-разработках и никогда не задумывались над базами данных. Комментарий на днях поставил этот большой знак вопроса: «Я делаю это очень плохо», о котором не может обвинить ни один уважающий себя разработчик. Я прочитаю, спасибо за отправную точку. – Hammerstein

+0

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

+0

@Marcus: еще хуже, я работал в более чем 1 магазине, который * дал мандат * суррогатным клавишам автоматического увеличения, даже для таблиц, которые имеют вполне логичные и полезные натуральные ключи. – MusiGenesis

1

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

+0

Спасибо за ответ. Я не изучал базы данных годами, и даже тогда я делал то, что мне показывали, а не понимал. Наверное, я взял ответ из контекста. Спасибо за разъяснения. – Hammerstein

0

Автоинкрементные идентификаторы и нормализация не связаны (т. Е. Вы можете использовать автоматически увеличивающиеся идентификаторы в де-нормированной базе данных или иметь нормализованную базу данных, которая не использует автоматически увеличивающиеся идентификаторы).

+0

Чтобы быть более понятным, человек, который «отделялся», скорее всего, нарушил нормальную форму, выбирая суррогатный ключ над естественным ключом для своего конкретного случая. Действительно не имело значения, что ключ суррогата также оказался ключом автоматического инкремента. –

+0

Спасибо за помощь. Время чтения. – Hammerstein

+0

@Marcus: Я, конечно, надеюсь, что никто не был «разобран» только для использования суррогатного ключа. Это не совсем решительная дискуссия. – MusiGenesis

2

КОМПОЗИТА PK ПОДХОД

drop table if exists users; 
create table users(
user_id int unsigned not null auto_increment primary key, -- clustered auto_inc PK 
username varbinary(32) not null, 
unique key users_username_idx(username) 
)engine=innodb; 

insert into users (username) values ('f00'),('bar'),('bish'),('bash'),('bosh'),('F00'); 

drop table if exists user_friends; 
create table user_friends(
user_id int unsigned not null, 
friend_user_id int unsigned not null, 
primary key (user_id, friend_user_id) -- clustered composite PK 
)engine=innodb; 

insert into user_friends values 
(1,2),(1,3), (2,1),(2,5), (3,5), (4,1),(4,2),(4,3),(4,5),(4,6), (5,4),(5,1); 

большая часть времени я запрашиваю user_friends желающего перечислить все друг для данного пользователя поэтому мои запросы воспользовавшись кластеризированного первичного ключа (user_id, friend_user_id)

select * from user_friends where user_id = 4; -- uses PK index 

, если я хочу, чтобы удалить друга я составную PK поэтому необходимо указать user_id и friend_user_id, что я хочу, чтобы удалить - бот h части ключа должны быть удовлетворены. У этого есть привычка сделать вашу прикладную логику немного более сложной.

delete from user_friends where user_id = 4 and user_friend_id = 5; -- uses PK index 

AUTO INC PK ПОДХОД (таблица пользователей остается неизменным)

drop table if exists user_friends; 
create table user_friends(
friend_id int unsigned not null auto_increment primary key, -- clustered auto_inc PK 
user_id int unsigned not null, 
friend_user_id int unsigned not null, 
unique key user_friends_idx (user_id, friend_user_id) -- non clustered secondary index 
)engine=innodb; 

большую часть времени я запрашиваю user_friends хотел перечислить всех друзей для данного пользователя в этом случае я могу Не используйте первичный ключ, и мне нужно создать дополнительный индекс (user_id, friend_user_id). Теперь у меня есть 2 индекса на этой таблице индекс PK , обеспечивающий целостность объекта и вторичный индекс, который помогает оптимизировать мои запросы.

Добавление вторичного индекса связано с его стоимостью.вставки/удаления теперь имеют значение . Обновление 2 индекса по сравнению с одним индексом составного ключа и занимает больше дискового пространства.

select * from user_friends where user_id = 4; -- uses secondary index not PK 

Однако, если я хочу, чтобы удалить друга я могу использовать friend_id PK это упрощает мою логику приложения , как я могу удалить 1 строку легко только с помощью ПК.

delete from user_friends where friend_id = 10; -- uses PK index 

Это вероятно не большой пример двух типов подходов, но это должно дать вам некоторые идеи в почему кластеризованные композитные индексы хороши для использования в разы :)

+0

Благодарим вас за примеры, код всегда помогает упростить ситуацию. Я ценю, что вы нашли время. – Hammerstein

+0

@ Hammerstein не проблема, надеюсь, что это поможет :) –