Внешний ключ автоматически создает индекс?

390

Мне сказали, что если я получу внешний ключ от двух таблиц, то SQL Server создаст что-то похожее на индекс в дочерней таблице. Мне трудно поверить, что это правда, но я не могу найти многое, связанное именно с этим.

Моя настоящая причина спрашивать это потому, что мы испытываем очень медленное время ответа в операторе удаления для таблицы, которая, вероятно, имеет 15 связанных таблиц. Я спросил нашего парня из базы данных, и он сказал, что если на полях есть внешний ключ, то он действует как индекс. Каков ваш опыт с этим? Стоит ли добавлять индексы ко всем полям внешнего ключа или это просто ненужные накладные расходы?

Ник ДеВоре
источник
У меня такое же понимание, как и у вашего парня из БД, - что ФК фактически создают индекс.
Винни
9
Нет - FK НЕ создает индекс автоматически. Имеет смысл создать его, но он не выполняется автоматически SQL Server.
marc_s
47
не глупо спрашивать это вообще!
marc_s
5
Если вы получаете медленное удаление и на таблицу, на которую вы удаляете ссылки из других таблиц, вы, вероятно, получите повышение производительности, проиндексировав внешние ключи в других таблицах. Это связано с тем, что когда SQL удаляет строку, ему необходимо проверить ссылочную целостность строки. Для этого, очевидно, необходимо проверить, что не существует других строк, ссылающихся на удаляемую строку.
Ноэль Кеннеди
3
Я бы сказал, что парень из базы данных, который не знал этого, должен серьезно нуждаться в обучении. Сотрудники базы данных несут ответственность за производительность, это их работа, знать такие вещи. Это говорит о грубой некомпетентности.
HLGEM

Ответы:

343

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

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

Поэтому имеет смысл индексировать любые столбцы, включенные в FK, но сам по себе FK не является индексом.

Ознакомьтесь с прекрасной статьей Кимберли Триппа "Когда SQL Server прекратил помещать индексы в столбцы внешнего ключа?" ,

marc_s
источник
Ага. Я почти уверен, что PostgreSQL создает индекс. Я уверен, что MySQL делает. Создание индекса имеет массу смысла, но ЭТО НЕ ТРЕБУЕТСЯ. В конце концов, зачем ссылаться на что-то, если каждый раз, когда БД просматривает его, она должна выполнять сканирование таблицы?
MBCook
Эта статья, упомянутая выше, немного сбивает с толку, потому что SQL-сервер или любая другая база данных никогда не помещает индекс в FK.
всингх
7
@ Vsingh: это именно то, что статья пытается передать - распространенное заблуждение, что FK автоматически создает индекс - он этого не делает.
marc_s
5
@MBCook Нет, PostgreSQL никак не (по крайней мере в 9.2 или любой предыдущей версии) автоматически создает индекс на ссылающейся стороне внешнего ключа отношения , определенное с REFERENCES. Он автоматически создает UNIQUEиндекс для ограничения PRIMARY KEYили или UNIQUEи требует, чтобы UNIQUEиндекс присутствовал для ссылочной стороны отношения внешнего ключа, но автоматически ничего не делает для ссылочной стороны, хотя часто рекомендуется создать его самостоятельно. Смотрите stackoverflow.com/questions/970562/…
Крейг Рингер
16
Путаница может существовать, потому что MySQL InnoDB и требует, и автоматически создает индекс при добавлении внешнего ключа - dev.mysql.com/doc/refman/5.5/en/…
humbads
42

Вау, ответы есть по всей карте. Итак, в документации сказано:

Ограничение FOREIGN KEY является кандидатом на индекс, потому что:

  • Изменения ограничений PRIMARY KEY проверяются с помощью ограничений FOREIGN KEY в связанных таблицах.

  • Столбцы внешнего ключа часто используются в критериях соединения, когда данные из связанных таблиц объединяются в запросах путем сопоставления столбцов в ограничении FOREIGN KEY одной таблицы со столбцами первичного или уникального ключа в другой таблице. Индекс позволяет Microsoft® SQL Server ™ 2000 быстро находить связанные данные в таблице внешнего ключа. Однако создание этого индекса не является обязательным требованием. Данные из двух связанных таблиц могут быть объединены, даже если между таблицами не определены ограничения PRIMARY KEY или FOREIGN KEY, но отношение внешнего ключа между двумя таблицами указывает на то, что эти две таблицы были оптимизированы для объединения в запросе, который использует ключи как его критерии.

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

Ишай
источник
5
Точно - это CANDIDATE для индекса - но он не создается автоматически как единое целое! Совершенно ясно, на самом деле, ИМХО :-)
marc_s
4
Я нашел эту часть запутанной: «отношение внешнего ключа между двумя таблицами указывает, что эти две таблицы были оптимизированы для объединения в запросе, который использует ключи в качестве своих критериев». Это должно читать "... две таблицы должны быть оптимизированы ..."
Ишай
18

Нет, неявный индекс для полей внешнего ключа отсутствует, иначе почему бы Microsoft сказала: «Создание индекса по внешнему ключу часто полезно» . Ваш коллега может быть запутанным ключевое поле иностранного в ссылающейся таблице с первичным ключом в указанных к таблице - первичные ключи действительно создать неявный индекс.

Майкл Боргвардт
источник
что такое "неявный индекс"? это просто означает, что есть дерево ab * без его создания?
Стефани Пейдж
1
@Stephanie Page: это выражение, которое я только что придумал, чтобы этот ответ означал индекс, который создается автоматически. Если вы объявляете первичный ключ, SQL-сервер автоматически создает и индексирует его. Но не если вы объявляете внешний ключ (некоторые другие системы БД делают).
Майкл Боргвардт
7

SQL Server автоматически создает индексы для первичных ключей, но не для внешних ключей. Создайте индекс для внешних ключей. Это, вероятно, стоит накладных расходов.

Пол Сонье
источник
6

Скажем, у вас есть большой стол под названием заказы и маленький стол под названием клиенты. Существует внешний ключ от заказа к клиенту. Теперь, если вы удаляете клиента, Sql Server должен проверить, что нет орфанных заказов; если есть, то возникает ошибка.

Чтобы проверить, есть ли какие-либо заказы, Sql Server должен искать в таблице больших заказов. Теперь, если есть индекс, поиск будет быстрым; если нет, поиск будет медленным.

Поэтому в этом случае медленное удаление может быть объяснено отсутствием индекса. Особенно если Sql Server придется искать 15 больших таблиц без индекса.

PS Если внешний ключ имеет значение ON DELETE CASCADE, Sql Server все равно должен выполнить поиск в таблице заказов, но затем удалить все заказы, которые ссылаются на удаленного клиента.

Andomar
источник
Точно - вот почему индекс FK имеет большой смысл (большую часть времени)
marc_s
1
Большую часть времени? Кажется, это тот случай, когда удаление от родителя. Если большую часть времени вы удаляете от родителей, я думаю, это правда.
Стефани Пейдж
6

Внешние ключи не создают индексы. Только ограничения альтернативного ключа (UNIQUE) и ограничения первичного ключа создают индексы. Это верно в Oracle и SQL Server.

Сандип Канури
источник
3

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

Гэндальф
источник
3

Строго говоря, внешние ключи не имеют абсолютно никакого отношения к индексам, да. Но, как указали вышеупомянутые ораторы, имеет смысл создать такой, чтобы ускорить поиск в FK. Фактически, в MySQL, если вы не укажете индекс в объявлении FK, механизм (InnoDB) создаст его для вас автоматически.

shylent
источник
3

В PostgeSql вы можете самостоятельно проверить наличие индексов, если нажмете \ d имя_таблицы

Вы увидите, что индексы btree были автоматически созданы для столбцов с первичным ключом и уникальными ограничениями, но не для столбцов с внешними ключами.

Я думаю, что это отвечает на ваш вопрос, по крайней мере, для Postgres.

Грегор
источник
Извините, я не заметил, что вопрос касается MS SQL Server, но после публикации ответа. Возможно, он еще может кому-то помочь ...
Грегор
2

Я заметил, что Entity Framework 6.1, на который указывает MSSQL, автоматически добавляет индексы для внешних ключей.

Люк Пуплетт
источник
Я не верю, что это происходит, если вы вручную помечаете столбец как часть индекса (например, если вы создаете составной индекс для нескольких элементов)
Роуланд Шоу,
0

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

Талха Ф.
источник