В EF Code First общата причина, поради която бихте моделирали връзка с външен ключ, е възможността за навигация между обекти. Помислете за прост сценарий на Country
и City
, с нетърпеливо зареждане, дефинирано за следния LINQ оператор:
var someQuery =
db.Countries
.Include(co => co.City)
.Where(co => co.Name == "Japan")
.Select(...);
Това ще доведе до заявка по следния начин:
SELECT *
FROM Country co
INNER JOIN City ci
ON ci.CountryId = co.ID
WHERE co.Name = 'Japan';
Без индекс на външния ключ на City.CountryId
, SQL ще трябва да сканира таблицата Cities, за да филтрира градовете за страната по време на JOIN.
FK индексът също така ще има предимства в производителността, ако редовете бъдат изтрити
от родителската таблица Държава, тъй като референтната цялост ще трябва да открие наличието на всички свързани редове за град (независимо дали FK има ON CASCADE DELETE
определени или не).
TL;DR
Индекси на външни ключове са препоръчително , дори ако не филтрирате директно външния ключ, той пак ще е необходим в Joins. Изключенията от това изглеждат доста измислени:
-
Ако селективността на външния ключ е много ниска, напр. в горния сценарий, ако 50% от ВСИЧКИ градове в таблицата с държави са в Япония, тогава индексът не би бил полезен.
-
Ако всъщност никога не навигирате през връзката.
-
Ако никога не изтриете редове от родителската таблица (или опитате да актуализирате на PK) .
Едно допълнително съображение за оптимизиране е дали да се използва външният ключ в Clustered Index
на дъщерната таблица (т.е. клъстерни градове по държави). Това често е от полза при релации родителски:дъщерни таблици, където е обичайно да се извличат всички дъщерни редове за родителя едновременно.