#postgresql
#postgresql
Вопрос:
Когда я создаю таблицу user:
pk
id | int
И друг таблицы:
pk, fk | pk, fk
user_id | friend_id
Насколько я понимаю, composite pk создает уникальный индекс user_id friend_id внутри, и этот индекс используется для внешнего ключа user_id. Но нужно ли мне создавать индекс для friend_id, потому что индекс в составной таблице друзей pk не будет работать для friend_id (он второй в составном pk)?
SQL:
CREATE TABLE public."user"
(
id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
)
CREATE TABLE public.user_friend
(
user_id integer NOT NULL,
friend_id integer NOT NULL,
CONSTRAINT user_friend_pkey PRIMARY KEY (user_id, friend_id),
CONSTRAINT user_friend_friend_id_fkey FOREIGN KEY (friend_id)
REFERENCES public."user" (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT user_friend_user_id_fkey FOREIGN KEY (user_id)
REFERENCES public."user" (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
)
CREATE INDEX fki_user_friend_friend_id_fkey
ON public.user_friend USING btree
(friend_id ASC NULLS LAST)
TABLESPACE pg_defau<
Комментарии:
1. Да, для запроса, который ищет пользователей, у которых есть x в качестве друга, такой индекс был бы полезен. Однако то, что существуют ссылки на внешние ключи, в значительной степени не имеет значения для этого.
2. @Bergi я не буду использовать такой запрос. Но почему это не имеет значения, если каждый раз, когда я вставляю в таблицу друзей, postgres должен быть уверен, что с внешними ключами все в порядке, и если для проверки user_id он может использовать индекс первичного ключа, для friend_id это не сработает?
3. Внешние ключи указывают на
user.id
столбец, если я правильно понял? (Было бы полезно, если бы вы могли опубликовать определения таблиц как SQL). Это будет использовать индекс первичного ключаid
вuser
таблице для проверки правильности вставленныхuser_id
значений иfriend_id
значений. Индексы вfriend
таблице не используются для проверки целостности внешнего ключа. (Однако они становятся актуальными при удалении или обновленииid
of auser
).4. @Bergi опубликовал sql. Да, есть каскад для каждого столбца. Пожалуйста, ответьте, чтобы я мог его принять. Думаю, теперь я понимаю. Вставки используют пользовательский индекс, но если я изменю идентификатор пользователя, мне понадобится индекс в таблице друзей.
5. @Bergi rarelly, хм, ты прав, тогда мне действительно не нужен индекс для друзей.
Ответ №1:
Насколько я понимаю, composite pk создает уникальный индекс user_id friend_id intenally
ДА.
и этот индекс используется для внешнего ключа user_id.
Не совсем, нет.
Здесь есть два случая:
INSERT
илиUPDATE
вuser_friend
таблице. Конечно, ему нужно будет проверить первичный ключ таблицы (иuser_friend_pkey
для этого он будет использовать индекс). Для ограничений внешнего ключа потребуется только проверитьuser_id
friend_id
, существуют ли значения и вuser
таблице, и для них будет использоваться индекс, созданныйuser
первичным ключом.- редактор
UPDATE
DELETE
наuser
столе. Он должен будет проверить, было ли в таблице указано старое значениеuser_friend
, и действовать в соответствии со стратегиейCASCADE
orRESTRICT
. Чтобы найти эту строкуuser_friend
, он будет использовать индексы вклuser_id
и вклfriend_id
, если они существуют.
Но нужно ли мне создавать индекс для friend_id, потому что индекс в составной таблице друзей pk не будет работать для friend_id
Да, поиск по friend_id
происходит медленно без дополнительного индекса. Вам это нужно только в том случае, если вы хотите найти пользователей, у которых есть x в качестве друга, или когда обновления / удаления user
не должны быть медленными.
Комментарии:
1. Просто чтобы убедиться, что если я «выберу * из user_friend где user_id = что-то» или для идентификатора ОБНОВЛЕНИЯ или УДАЛЕНИЯ пользователя в таблице user, мне не нужно создавать индекс user_id в таблице user_friend, потому что он будет использовать индекс pk в таблице user_friend.
2.
select * from friend_user where user_id=smth
будет нормально работать сuser_friend_pkey
индексом, да.update "user" set id=smth
/delete "user" where id=smth
также будет использовать этот индекс для обновленияuser_friend
строк,user_id
ссылки на которые обновлены / удаленыuser.id
. Однако для обновленияuser_friend
строк,friend_id
ссылки на которые обновлены / удаленыuser.id
, это не сработает — для этого вам нужен дополнительный индексfriend_id
.