КОМПОЗИЦИОННЫЙ ПК ПОДХОД
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
Вероятно, это не лучший пример двух типов подходов, но он должен дать вам некоторые идеи о том, почему кластерные составные индексы иногда хороши для использования: