КОМПОЗИТА 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
Это вероятно не большой пример двух типов подходов, но это должно дать вам некоторые идеи в почему кластеризованные композитные индексы хороши для использования в разы :)
Спасибо за ответ и ссылки. Мои усилия в основном были сосредоточены на настольных и веб-разработках и никогда не задумывались над базами данных. Комментарий на днях поставил этот большой знак вопроса: «Я делаю это очень плохо», о котором не может обвинить ни один уважающий себя разработчик. Я прочитаю, спасибо за отправную точку. – Hammerstein
Там, где доступны натуральные ключи, выбор суррогатного ключа над естественным ключом часто выполняется по какой-либо причине производительности, и, хотя он может нарушить нормальную форму, он может быть законным выбором для дизайнера. Общее правило заключается в том, что, если у вас нет конкретной, объективной причины разрыва нормальной формы, не делайте этого. Некоторые люди слепо выбирают суррогатные ключи автоинкремента для каждого стола, не имея законной причины. –
@Marcus: еще хуже, я работал в более чем 1 магазине, который * дал мандат * суррогатным клавишам автоматического увеличения, даже для таблиц, которые имеют вполне логичные и полезные натуральные ключи. – MusiGenesis