Чи покращує зовнішній ключ ефективність запитів?


149

Припустимо, у мене є 2 таблиці, товари та категорії товарів. Обидві таблиці мають відношення до CategoryId. І це запит.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

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

Тому я повинен створити індекс на Products.CategoryId. Коли я знову створюю план виконання, обидві таблиці виконують пошук індексу. І орієнтовна вартість піддерев'я значно зменшується.

Мої запитання:

  1. Окрім ФК допомагає у обмеженні стосунків, чи має вона якусь іншу корисність? Це покращує ефективність запитів?

  2. Чи потрібно створити індекс у всіх стовпцях FK (сподобалось Products.CategoryId) у всіх таблицях?

Відповіді:


186

Іноземні ключі - це референтний інструмент цілісності, а не інструмент продуктивності. Принаймні в SQL Server, створення FK не створює пов'язаний індекс, і ви повинні створювати індекси на всіх полях FK, щоб покращити час пошуку.


40
Хороші моделі (як правило) працюють краще.
Кенні Евітт

10
"Іноземні ключі є інструментом відносної цілісності" - будь ласка, обережно використовуйте слово "реляційний". Зовнішні ключі - це концепція бази даних, коротка рука для референтного обмеження цілісності. Вони не входять до реляційної моделі. Я припускаю, що ви написали помилку.
одного дня, коли

7
@Kenny Часто так, але іноді краща модель коштує дорожче. Справа в суті: іноземні ключі спричиняють більше обробки, не менше.
Ганс

8
зовнішні ключі роблять підвищення продуктивності, принаймні , в MySQL. Більше того, ви праві, створення ФК не створює індекс; для створення ФК потрібен індекс
Фелікс Ганьон-Греньє,

15
Ця відповідь є вкрай марною, оскільки не відповідає на питання. Це здорово знати , що зовнішні ключ не призначені , щоб мати (позитивний) ефект на продуктивність, але питання щодо реальності, а не наміри.
Іоанн

58

Іноземні ключі можуть покращити (і зашкодити) продуктивність

  1. Як зазначено тут: Зовнішні ключі підвищують продуктивність

  2. Ви завжди повинні створювати індекси на стовпцях FK, щоб зменшити кількість пошукових запитів. SQL Server не робить цього автоматично.

Редагувати

Оскільки тепер посилання здається мертвим (кудо, щоб Кріс помітив) , нижче показано суть того, чому іноземні клавіші можуть покращити (і нашкодити) продуктивності.

Чи може зовнішній ключ покращити ефективність

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

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


3
Ось посилання, яке детально описує способи зниження продуктивності devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr

3
Це має сенс, але ви зіткнетеся з цим лише за допомогою масивного оператора видалення. Можливо, слід зробити висновок, що в OLAP-середовищах неіндексований FK покращить продуктивність, а в середовищі OLTP - знизить продуктивність.
Lieven Keersmaekers

1
Посилання у цій відповіді мертве. Це прикро, оскільки це єдиний аргумент для покращення продуктивності ФК.
Кріс Москіні

1
@ChrisMoschini - я ще не помітив твого коментаря. Як ви вже згадували, посилання є мертвою, але суть її згадується в новому посиланні (з деталями), яке я опублікував.
Lieven Keersmaekers

2
Посилання Wayback Machine для Win! Статтю можна також знайти на SQLMag.com, тут .
Джон Ейсбренер

15

Іноземний ключ - це концепція СУБД для забезпечення цілісності бази даних.

Будь-які наслідки / покращення продуктивності будуть специфічними для використовуваної технології бази даних і є вторинними для цілей зовнішнього ключа.

Доброю практикою в SQL Server є забезпечення того, щоб усі зовнішні ключі мали принаймні некластеризований індекс на них.

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


9
@Kenny Evitt, якщо у вас немає цілісності, ваші дані марні. Я вважаю, що продається дуже легко.
HLGEM

@HLGEM Отримати помилку 404 час від часу все ще досить терпимо. Маючи виняткову пропускну здатність взамін використання дешевших ресурсів та менш складних систем, тепер це продається дуже легко. Вас може зацікавити теорема CAP .
Даніель Дінніс

8
@Daniel Dinnyes, цілісність даних - це не помилка 404. Йдеться про наявність корисних даних. Йдеться про не втрату замовлень та фінансових даних для звітів, наприклад, через некомпетентність розробників. Не існує ВИКЛЮЧЕННЯ для не використання сторонніх ключів.
HLGEM

2
Я згоден з HLGEM. Дозволити коду обробляти цілісність - це не завжди гарна ідея. Дані часто використовуються для прийняття рішень, але якщо дані пошкоджені, то рішення не буде точним.
lepe

1
"Іноземні ключі є інструментом відносної цілісності" - будь ласка, обережно використовуйте слово "реляційний". Зовнішні ключі - це концепція бази даних, коротка рука для референтного обмеження цілісності. Вони не входять до реляційної моделі. Я припускаю, що ви написали помилку.
одного дня, коли

4

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


3

Ви можете використовувати його, щоб зробити запит більш ефективним. Це дозволяє вам реструктуризувати запити в SQL Server, щоб використовувати зовнішнє з'єднання замість внутрішнього, яке видаляє сервери sql, необхідність перевіряти, чи немає у стовпці нуля. Вам не потрібно ставити цей кваліфікатор, оскільки зовнішні ключові відносини вже примушують це до вас.

Отже це:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

Стає таким:

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

Це не обов'язково забезпечує величезну ефективність у невеликих запитах, але коли таблиці набувають великих розмірів, це може бути ефективнішим.


3
Не тільки зовнішні з'єднання, як правило, менш ефективні, ніж внутрішні з'єднання ( stackoverflow.com/a/2726683/155892 ), тепер ваші запитання вводять в оману: ви покладаєтесь на базу даних, щоб неявно перетворити зовнішні з'єднання у внутрішні з'єднання (відновлення продуктивності) а не просто робити це явно
Марк Совул

2

Для MySQL 5.7 це, безумовно, може пришвидшити запити, що включають кілька приєднань напрочуд добре!

Я використав "пояснити", щоб зрозуміти свій запит, і виявив, що я приєднуюся до 4-5 таблиць - де жодні ключі не використовуються. Я нічого не робив, окрім як додав зовнішній ключ до цих таблиць, результатом було 90% скорочення часу завантаження. Запити, які брали> 5, зараз займають 500 мс або менше.

Це НЕОБХІДНЕ поліпшення!

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

Крім цього, забезпечення референтної цілісності має і власні переваги від продуктивності. Це має ефект другого порядку - гарантувати, що таблиці, які мають зовнішній ключ, "оновлені" з іноземною таблицею. Скажімо, у вас є таблиця користувачів та таблиця коментарів, і ви робите певну статистику в таблиці коментарів. Можливо, якщо ви важко видалите користувача, ви також не хочете їх коментарів.


Чи таблиці мали необхідні індекси для генерації зовнішніх ключів, перш ніж ви додали їх?
Джордж

1

Додавання іноземного ключа до таблиці не підвищить ефективність, просто кажучи, якщо ви вставляєте запис у базу даних таблиць ProductCategories, спробуєте знайти стовпчик іноземного ключа, який має значення, яке існує у первинному ключі таблиці таблиці продуктів. операція накладається на вашу базу даних щоразу, коли ви додаєте новий запис у таблицю ProductCategories. Таким чином, додаючи зовнішній ключ, це не покращить роботу вашої бази даних, але вона подбає про цілісність вашої бази даних. Так, це покращить продуктивність вашого db, якщо ви перевіряєте цілісність за допомогою зовнішнього ключа, замість того, щоб виконувати багато запитів для перевірки записів, що існують у базі даних вашої програми.


0

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


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