W EF Code First ogólnym powodem modelowania relacji klucza obcego jest nawigacja między jednostkami. Rozważ prosty scenariusz Country
i City
, z gorliwym ładowaniem zdefiniowanym dla następującej instrukcji LINQ:
var someQuery =
db.Countries
.Include(co => co.City)
.Where(co => co.Name == "Japan")
.Select(...);
Spowoduje to zapytanie w następujący sposób:
SELECT *
FROM Country co
INNER JOIN City ci
ON ci.CountryId = co.ID
WHERE co.Name = 'Japan';
Bez indeksu klucza obcego w City.CountryId
, SQL będzie musiał przeskanować tabelę Miasta, aby przefiltrować miasta dla kraju podczas JOIN.
Indeks FK będzie miał również korzyści w zakresie wydajności, jeśli wiersze zostaną usunięte
z tabeli Kraj nadrzędny, ponieważ integralność referencyjna będzie musiała wykryć obecność wszystkich połączonych wierszy Miasta (niezależnie od tego, czy FK ma ON CASCADE DELETE
zdefiniowane lub nie).
TL;DR
Indeksy kluczy obcych są zalecane , nawet jeśli nie filtrujesz bezpośrednio klucza obcego, nadal będzie on potrzebny w sprzężeniach. Wyjątki od tego wydają się dość wymyślne:
-
Jeśli selektywność klucza obcego jest bardzo niska, np. w powyższym scenariuszu, gdyby 50% WSZYSTKICH miast w tabeli krajów znajdowało się w Japonii, Indeks nie byłby przydatny.
-
Jeśli faktycznie nigdy nie poruszasz się po związku.
-
Jeśli nigdy nie usuniesz wierszy z tabeli nadrzędnej (lub nie spróbujesz aktualizacji w PK).
Jedną z dodatkowych kwestii dotyczących optymalizacji jest to, czy użyć klucza obcego w Clustered Index
tabeli podrzędnej (tj. klaster Cities by Country). Jest to często korzystne w relacjach tabel nadrzędny :podrzędny, gdzie powszechne jest jednoczesne pobieranie wszystkich wierszy podrzędnych dla rodzica.