Чи іноземний ключ автоматично створює індекс?


389

Мені сказали, що якщо я вкажу дві таблиці, SQL Server створить щось подібне до індексу в дочірній таблиці. Мені важко вірити, що це правда, але я не можу знайти багато, що стосується конкретно цього.

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


Я розумію те, що і ваш хлопець із БД - що ФК насправді створює індекс.
Вінні

9
Ні - це FK робить НЕ автоматично створити індекс. Є сенс створити його - але це НЕ робиться автоматично SQL Server.
marc_s

47
зовсім не дурно про це запитати!
marc_s

5
Якщо ви отримуєте повільні видалення та таблицю, яку ви видаляєте з посилань на інші таблиці, ви, ймовірно, отримаєте підвищення продуктивності, індексуючи зовнішні ключі в інших таблицях. Це тому, що коли SQL видаляє рядок, йому потрібно перевірити референтну цілісність на рядку. Для цього очевидно потрібно перевірити, чи немає інших рядків, що посилаються на рядок, який ви видаляєте.
Ноель Кеннеді

3
Я б сказав, що хлопець із бази даних, який цього не знав, повинен серйозно потребувати навчання. Люди, що працюють з базами даних, відповідають за продуктивність, їхня робота - знати такі речі. Це говорить про грубу некомпетентність.
HLGEM

Відповіді:


343

Іноземний ключ - це обмеження, відношення між двома таблицями - яке не має нічого спільного з індексом як таке.

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

Отже, має сенс індексувати будь-які стовпці, що беруть участь у ФК, але ФК сам по собі не є індексом.

Перегляньте чудову статтю Кімберлі Тріппа "Коли SQL Server перестав ставити індекси на стовпці іноземних ключів?" .


Так. Я просто про те, що PostgreSQL створює індекс. Я впевнений, що робить MySQL. Створення індексу має багато сенсу, але це НЕ ПОТРІБНО. Зрештою, навіщо щось посилатись, якщо кожен раз, коли БД шукає, він повинен робити таблиці?
MBCook

Ця стаття, згадана вище, є дещо заплутаною, оскільки сервер SQL або будь-яка інша база даних ніколи не ставить індекс на FK.
vsingh

7
@vsingh: саме так намагається донести стаття - це поширене оману, що ФК автоматично створює індекс - це не робить.
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/uk/…
humbads

42

Нічого собі, відповіді по всій карті. Отже, Документація говорить:

Обмеження ЗАМЕЧЛЕНОГО КЛЮЧА є кандидатом на показник, оскільки:

  • Зміни в обмеженнях PRIMARY KEY перевіряються обмеженнями FOREIGN KEY у відповідних таблицях.

  • Стовпці із зовнішнім ключем часто використовуються в критеріях приєднання, коли дані із пов’язаних таблиць поєднуються у запитах, шляхом зіставлення стовпців (ив) обмеженням ІНТЕРНЕТ-КЛЮЧ однієї таблиці з первинним або унікальним стовпчиком ключів в іншій таблиці. Індекс дозволяє Microsoft® SQL Server ™ 2000 швидко знаходити пов'язані дані в таблиці іноземних ключів. Однак створення цього індексу не є вимогою. Дані з двох пов’язаних таблиць можуть бути об'єднані, навіть якщо між таблицями не визначено обмежень PRIMARY KEY або FOREIGN KEY, але співвідношення зовнішнього ключа між двома таблицями вказує на те, що обидві таблиці були оптимізовані для об'єднання в запиті, який використовує ключі як її критерії.

Тож здається досить зрозумілим (хоча документація дещо заплутана), що насправді це не створює індекс.


5
Саме так - це КАНДИДАТ для індексу - але він не створюється автоматично як один! Насправді зрозуміло, IMHO :-)
marc_s

4
Я визнав цю частину заплутаною: "Зв'язок із зовнішніми ключами між двома таблицями вказує на те, що дві таблиці були оптимізовані для об'єднання в запит, який використовує ключі як свої критерії". Тут слід сказати "... дві таблиці повинні бути оптимізовані ..."
Ісіхай

18

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


що таке "неявний індекс"? це просто означає, що є дерево ab *, не створюючи його?
Стефанія Сторінка

1
@Stephanie Page: Цей вираз я просто склав, щоб ця відповідь означала індекс, який автоматично створюється. Якщо ви оголосили первинний ключ, SQL-сервер автоматично створює та індексує його. Але якщо ви не оголосите іноземний ключ (це роблять деякі інші системи БД).
Майкл Боргвардт

7

SQL Server автоматично створює індекси для первинних ключів, але не для іноземних ключів. Створіть індекс для іноземних ключів. Мабуть, варто накладні витрати.


6

Скажімо, у вас є велика таблиця, яка називається замовленнями, і маленька таблиця з назвою клієнтів. Існує іноземний ключ від замовлення до замовника. Тепер, якщо ви видалите клієнта, сервер Sql повинен перевірити, чи немає замовлень-сиріт; якщо є, це викликає помилку.

Щоб перевірити, чи є замовлення, сервер Sql повинен здійснити пошук у великій таблиці замовлень. Тепер, якщо є індекс, пошук буде швидким; якщо його немає, пошук буде повільним.

Тож у цьому випадку повільне видалення можна пояснити відсутністю індексу. Особливо, якщо сервер Sql повинен був шукати 15 великих таблиць без індексу.

PS Якщо в зовнішньому ключі є ВИКЛИКАТИ КАСКАД, Sql Server все ще повинен шукати таблицю замовлень, але потім видаляти будь-які замовлення, які посилаються на видаленого клієнта.


Саме так - це причина, коли індекс у ФК має багато сенсу (більшість часу)
marc_s

1
Більшість часу? Здається, це стосується видалення з батьків. Якщо більшу частину часу ви видаляєте з батьків, я думаю, це правда.
Стефанія Сторінка

6

Іноземні ключі не створюють індексів. Тільки альтернативні обмеження ключів (UNIQUE) та обмеження первинного ключа створюють індекси. Це вірно в Oracle і SQL Server.


3

Не наскільки мені відомо. Іноземний ключ лише додає обмеження, що значення в дочірньому ключі також буде представлено десь у батьківському стовпчику. Це не говорить базі даних, що дочірній ключ також потрібно індексувати, лише обмежувати.


3

Строго кажучи, іноземні ключі абсолютно не мають нічого спільного з індексами, так. Але, як вказували динаміки вище мене, є сенс створити такий, щоб пришвидшити пошук у FK. Насправді, у MySQL, якщо ви не вказали індекс у своїй декларації FK, двигун (InnoDB) створює його автоматично для вас.


3

У PostgeSql ви можете перевірити наявність індексів, якщо ви натиснули \ d ім'я таблиці

Ви побачите, що btree-індекси створюються автоматично на стовпцях з первинним ключем та унікальними обмеженнями, але не на стовпцях із сторонніми ключами.

Я думаю, що це відповість на ваше запитання хоча б для постгресів.


На жаль, я не помітив, що питання стосується MS SQL Server, але після публікації відповіді. Можливо, це ще може комусь допомогти ...
Грегор

2

Я зауважую, що Entity Framework 6.1, вказаний на MSSQL, автоматично додає індекси на зовнішні ключі.


Я не вірю, що це робиться, якщо ви вручну позначите стовпчик як частину індексу (наприклад, якщо ви створюєте складений індекс для кількох членів)
Rowland Shaw

0

InnoDB вимагає індексів на зовнішніх ключів і довідкових ключів , так що зовнішні ключі перевірки можуть бути швидко і не вимагає сканування таблиці. У таблиці посилань повинен бути індекс, де стовпці іноземного ключа вказані як перші стовпці в тому ж порядку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.