Как правильно индексировать таблицу ассоциаций многих-многих?
В типичном много-много расположении, подобном этому...
Movies Actors Movies_Actors
------ ------ -------------
movie_ID actor_ID FK_movie_ID
title name FK_actor_ID
... как следует индексировать таблицу ассоциации ('Movies_Actors'
) для оптимальной скорости чтения?
Обычно я вижу, что это делается только с помощью составного первичного ключа в таблице ассоциации, например:
CREATE TABLE Movies_Actors (
FK_movie_ID INTEGER,
FK_actor_ID INTEGER,
PRIMARY KEY (FK_movie_ID, FK_actor_ID)
)
Однако это похоже на то, что индекс будет полезен только при поиске как movie_ID
, так и actor_ID
(хотя я не уверен, работает ли составной индекс для отдельных столбцов).
Поскольку как "то, что актеры в фильме X", так и "какие фильмы имеют актеры, в которых я был", будут общими запросами для этой таблицы, кажется, что в каждом столбце должен быть индивидуальный указатель, чтобы быстро найти актеров и фильмов самостоятельно. Эффективно ли это делает составной индекс? Если нет, то составной индекс кажется бессмысленным в этой таблице. А если составной индекс бессмыслен, что делать с первичным ключом? Ключ-кандидат, очевидно, является составной частью двух столбцов, но если итоговый составной индекс бессмыслен (он не должен быть?), Он кажется пустой.
Кроме того, эта ссылка добавляет некоторую путаницу и указывает, что даже полезно указать два составных индекса... один из них как (FK_movie_ID, FK_actor_ID)
, а другой в обратном порядке как (FK_actor_ID, FK_movie_ID)
, выбор которого является первичным ключом (и, как правило, кластеризованным) и который является "просто" уникальным составным индексом, основанным на том, какое направление больше запрашивается.
Какова реальная история? Совокупный индекс автоматически эффективно индексирует каждый столбец для поиска по одному или другому? Если таблица оптимальной (в скорости чтения, а не размер) таблицы имеет составной индекс в каждом направлении и по одному на каждый столбец? Каковы мечанки за сценой?
EDIT: я нашел этот связанный вопрос, который почему-то я не нашел перед публикацией...
Как правильно индексировать таблицу привязки для соединения "многие-ко-многим" в MySQL?
Ответы
Ответ 1
(хотя я не уверен, составной индекс также работает для отдельные столбцы).
Да, это возможно. Но только префикс: http://use-the-index-luke.com/sql/where-clause/the-equals-operator/concatenated-keys
Кроме того, эта ссылка добавляет некоторую путаницу и указывает, что это может быть даже полезно определить два составные индексы... один из них как (FK_movie_ID, FK_actor_ID) и другой в обратном порядке (FK_actor_ID, FK_movie_ID),
Это действительно то, что нужно сделать.
Возьмите один из них как индекс кластеризации, а другой - как некластеризованный индекс, который будет включать в себя ключ индекса кластеризации, поэтому нет необходимости включать этот столбец снова (спасибо в JNK).
CREATE CLUSTERING INDEX a on Movies_Actors (fk_movie_id, fk_actor_id);
CREATE NONCLUSTERING INDEX b on Movies_Actors (fk_actor_id);
Какова реальная история?
http://Use-The-Index-Luke.com/:)
Содержит ли составной индекс автоматически эффективно индексировать каждый столбец для поиск по одному или другому?
Нет. Только префикс индекса. Если у вас есть индекс (a, b, c), запрос a =? и b =? может использовать индекс. Однако c =? не может, и не может b =? и c =?.
Если оптимальный (при скорости чтения, не размер) имеют таблицу составной индекс в каждом направлении и по одному в каждом столбце?
Если вам нужно присоединиться в обоих направлениях, да ( "составной индекс в каждом направлении" ) и нет ( "по одному на каждый столбец" ).
Какова механика за сценой?
Ну, та же ссылка снова.
Говоря SQL Server, вы можете в конечном итоге также рассмотреть индексированное представление. Такое предварительное присоединение. Два индекса, как указано выше, также могут быть достаточно быстрыми.
Ответ 2
В SQL Server составной индекс может использоваться только для одного поиска по полю для первого столбца. Это означает, что у вас должен быть дополнительный индекс одного индекса на FK_actor_id
, если в этом запросе будут выполняться запросы без FK_Movie_id
.