Нужно ли мне создавать индексы по внешним ключам в Oracle?

121

У меня есть стол Aи стол B. Aимеет внешний ключ Bна Bпервичный ключ «S, B_ID.

По какой-то причине (я знаю, что есть законные причины) он не использует индекс, когда я объединяю эти две таблицы по ключу.

Нужно ли мне отдельно создавать индекс A.B_IDили должен ли это обеспечивать наличие внешнего ключа?

aw crud
источник

Ответы:

138

Ограничение внешнего ключа само по себе не обеспечивает индекс в Oracle - его нужно (и нужно) создать.

DCookie
источник
11
В некоторых базах данных создание ограничения внешнего ключа создает также индекс ... например, Jet Engine (файлы MSAccess, Firebird и MySQL)
bubi
17
Этот ответ бессмысленен без явной ссылки на конкретную реализацию базы данных. Конечно, вопрос помечен, oracleно это не сразу очевидно, когда вы попадаете сюда из поиска Google.
разработчикbmw
5
Я могу подтвердить, что PostgreSQL - по крайней мере, на момент написания этой статьи - не делает этого автоматически.
The
Тот же ответ для SQL Server (2016, Azure ...), насколько мне известно.
Pac0
Почему с Oracle нужно создавать индекс по внешнему ключу? Каковы последствия, если вы этого не сделаете?
Đỗ Công Bng,
46

Создание внешнего ключа не приводит к автоматическому созданию индекса на A.B_ID. Таким образом, с точки зрения производительности запросов, как правило, имеет смысл создать отдельный индекс для A.B_ID.

Если вы когда-нибудь удаляете строки в B, вы определенно хотите, чтобы A.B_ID был проиндексирован. В противном случае Oracle придется выполнять полное сканирование таблицы на A каждый раз, когда вы удаляете строку из B, чтобы убедиться, что нет потерянных записей (в зависимости от версии Oracle могут быть дополнительные последствия блокировки, но они уменьшаются в более поздних версиях Oracle).

Джастин Кейв
источник
1
А как насчет колонн ПФК? например, если у меня есть промежуточная таблица для отношения «многие ко многим», может ли я создать индекс для двух столбцов PFK этой таблицы?
Clamari
3
@Clamari - если у C есть первичный ключ (A_ID, B_ID), первичный ключ позаботится о возможности удаления из A. Если вы также хотите иметь возможность эффективно удалять из B, вам понадобится индекс B_ID.
Джастин Кейв
25

Просто для дополнительной информации: Oracle не создает индекс автоматически (как это делается для уникальных ограничений), потому что (а) это не требуется для обеспечения соблюдения ограничения и (б) в некоторых случаях он вам не нужен.

Однако в большинстве случаев вам может понадобиться создать индекс (фактически, в Oracle Apex есть отчет о «неиндексированных внешних ключах»).

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

Случай, когда я обычно не добавляю индекс, - это когда FK относится к таблице «статических данных», которая определяет домен столбца (например, таблицу кодов состояния), где обновления и удаления в родительской таблице никогда не выполняются. прямо в приложении. Однако если добавление индекса в столбец дает преимущества для важных запросов в приложении, то индекс все равно будет хорошей идеей.

Джеффри Кемп
источник
14

SQL Server никогда не помещал индексы в столбцы внешнего ключа автоматически - ознакомьтесь с отличным сообщением в блоге Кима Триппа о предыстории и истории этого городского мифа.

Однако обычно рекомендуется индексировать столбцы внешнего ключа - так что да, я бы рекомендовал убедиться, что каждый столбец FK имеет резервную копию индекса; не обязательно только для этого одного столбца - возможно, имеет смысл создать индекс для двух или трех столбцов, причем столбец FK будет первым в нем. Зависит от вашего сценария и ваших данных.

marc_s
источник
8

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

НО

Некоторые базы данных уже автоматически создают индексы для внешних ключей. Jet Engine (файлы Microsoft Access) Firebird MySQL

ДЛЯ УВЕРЕННОСТИ

SQL Server Oracle

НЕ

Буби
источник
3
Спасибо за упоминание, что FIrebird SQL делает это автоматически. Это именно то, что я искал.
user424855
1

Как и все, что касается производительности, это зависит от многих факторов, и здесь нет серебряной пули, например, в среде с очень высокой активностью поддержание индекса может быть неприемлемым.

Наиболее существенным здесь может показаться избирательность: если значения в индексе будут сильно дублироваться, то для повышения производительности может быть лучше отбросить индекс (если возможно) и разрешить сканирование таблицы.

onedaywhen
источник
1

Ограничения UNIQUE, PRIMARY KEY и FOREIGN KEY генерируют индексы, которые обеспечивают соблюдение или "обратное" ограничение (и иногда их называют резервными индексами). Ограничения PRIMARY KEY создают уникальные индексы. Ограничения FOREIGN KEY создают неуникальные индексы. Ограничения UNIQUE генерируют уникальные индексы, если все столбцы не допускают значения NULL, и генерируют неуникальные индексы, если один или несколько столбцов допускают значение NULL. Следовательно, если столбец или набор столбцов имеет ограничение UNIQUE, PRIMARY KEY или FOREIGN KEY, вам не нужно создавать индекс для этих столбцов для повышения производительности.

Chinmai
источник
Документы, на которые вы ссылаетесь, предназначены для Derby, встроенной базы данных Java, а не для Oracle.
Давос