MySQL - Каков правильный метод первичного ключа - PullRequest
3 голосов
/ 27 марта 2010

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

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

Ответы [ 4 ]

5 голосов
/ 27 марта 2010

Существует два основных метода выбора первичного ключа :

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

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

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

2 голосов
/ 27 марта 2010

КОМПОЗИЦИОННЫЙ ПК ПОДХОД

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

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

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

AUTO INC PK APPROACH (таблица пользователей остается прежней)

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

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

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

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

1 голос
/ 27 марта 2010

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

0 голосов
/ 27 марта 2010

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

...