Czy klucz obcy poprawia wydajność zapytań?

149

Załóżmy, że mam 2 tabele, produkty i kategorie produktów. Obie tabele mają relację na CategoryId. I to jest pytanie.

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;

Kiedy tworzę plan wykonania, tabela ProductCategories przeprowadza przeszukiwanie indeksu klastra, co jest zgodne z oczekiwaniami. Ale w przypadku produktów tabelowych wykonuje skanowanie indeksu klastra, co budzi wątpliwości. Dlaczego FK nie pomaga poprawić wydajności zapytań?

Więc muszę utworzyć indeks na Products.CategoryId. Kiedy ponownie tworzę plan wykonania, obie tabele wykonują przeszukiwanie indeksu. Szacowany koszt poddrzewa jest znacznie obniżony.

Moje pytania to:

  1. Oprócz FK pomaga w ograniczaniu relacji, czy ma jakąś inną użyteczność? Czy poprawia wydajność zapytań?

  2. Czy powinienem utworzyć indeks dla wszystkich kolumn FK (takich jak Products.CategoryId) we wszystkich tabelach?

Chaowlert Chaisrichalermpol
źródło

Odpowiedzi:

186

Klucze obce są referencyjnym narzędziem integralności, a nie narzędziem wydajności. Przynajmniej w SQL Server, utworzenie FK nie tworzy skojarzonego indeksu i powinieneś utworzyć indeksy dla wszystkich pól FK, aby skrócić czas wyszukiwania.

cmsjr
źródło
40
Dobre modele (ogólnie) działają lepiej.
Kenny Evitt
10
„Klucze obce są narzędziem integralności relacji” - prosimy o ostrożne używanie słowa „relacyjny”. Klucze obce to koncepcja bazy danych, krótka ręka dla ograniczenia integralności referencyjnej. Nie są częścią modelu relacyjnego. Zakładam, że popełniłeś literówkę.
kiedy
7
@Kenny Często tak, ale czasami lepszy model kosztuje więcej. Przykład: klucze obce powodują więcej przetwarzania, a nie mniej.
Hans,
8
klucze obce zrobić zwiększyć wydajność, przynajmniej w MySQL. Co więcej, masz rację, utworzenie FK nie tworzy indeksu; utworzenie FK wymaga indeksu
Félix Gagnon-Grenier
15
Ta odpowiedź jest prawie bezużyteczna, ponieważ nie odpowiada na pytanie. Dobrze jest wiedzieć, że klucze obce nie mają na celu (pozytywnego) wpływu na wydajność, ale pytanie dotyczyło rzeczywistości, a nie intencji.
John
58

Klucze obce mogą poprawić (i zaszkodzić) wydajność

  1. Jak stwierdzono tutaj: Klucze obce zwiększają wydajność

  2. Należy zawsze tworzyć indeksy w kolumnach FK, aby zmniejszyć liczbę wyszukiwań. SQL Server nie robi tego automatycznie.

Edytować

Ponieważ łącze wydaje się być teraz martwe (chwała dla Chrisa za zauważenie) , poniżej przedstawiono istotę tego, dlaczego klucze obce mogą poprawić (i zaszkodzić) wydajność.

Czy klucz obcy może poprawić wydajność

Ograniczenie klucza obcego poprawia wydajność w momencie odczytu danych, ale jednocześnie spowalnia wydajność w momencie wstawiania / modyfikowania / usuwania danych.

W przypadku czytania zapytania optymalizator może użyć ograniczeń klucza obcego do tworzenia bardziej wydajnych planów zapytań, ponieważ ograniczenia klucza obcego są wstępnie zadeklarowanymi regułami. Zwykle wiąże się to z pominięciem części planu zapytania, ponieważ na przykład optymalizator może zobaczyć, że ze względu na ograniczenie klucza obcego nie jest konieczne wykonywanie tej określonej części planu.

Lieven Keersmaekers
źródło
3
Oto link, który szczegółowo opisuje, w jaki sposób mogą obniżyć wydajność devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr
3
Ma to sens, ale napotkasz to tylko z ogromnym poleceniem usunięcia. Być może wniosek powinien być taki, że w środowiskach OLAP nieindeksowane FK poprawiłyby wydajność, podczas gdy w środowiskach OLTP obniżyłyby wydajność.
Lieven Keersmaekers
1
Link w tej odpowiedzi jest martwy. Jest to niefortunne, ponieważ jest to jedyny argument przemawiający za poprawą wydajności przez SK.
Chris Moschini,
1
@ChrisMoschini - do tej pory nie zauważyłem twojego komentarza. Jak wspomniałeś, link jest martwy, ale jego istota jest wspomniana w nowym linku (ze szczegółami), który opublikowałem.
Lieven Keersmaekers
2
Łącze Wayback Machine do wygranej! Artykuł można również znaleźć na SQLMag.com, tutaj .
John Eisbrener
15

Klucz obcy to koncepcja DBMS zapewniająca integralność bazy danych.

Wszelkie implikacje / ulepszenia dotyczące wydajności będą specyficzne dla używanej technologii baz danych i będą drugorzędne w stosunku do celu klucza obcego.

W SQL Server dobrą praktyką jest upewnienie się, że wszystkie klucze obce mają co najmniej indeks nieklastrowy.

Mam nadzieję, że to wszystko wyjaśni, ale możesz poprosić o więcej szczegółów.

John Sansom
źródło
9
@Kenny Evitt, jeśli nie masz integralności, Twoje dane są bezużyteczne. Uważam, że sprzedaje się bardzo łatwo.
HLGEM
@HLGEM Pojawianie się od czasu do czasu błędu 404 jest nadal całkiem znośne. Mając wyjątkową przepustowość w zamian przy użyciu tańszych zasobów i mniej złożonych systemów, teraz również łatwo się sprzedaje. Możesz być zainteresowany twierdzeniem CAP .
Daniel Dinnyes
8
@Daniel Dinnyes, integralność danych nie polega na uzyskaniu błędu 404. Chodzi o posiadanie użytecznych danych. Chodzi o to, aby nie tracić zamówień i danych finansowych do raportów np. Z powodu niekompetencji deweloperów. Nie ma wymówki za nieużywanie kluczy obcych.
HLGEM
2
Zgadzam się z HLGEM. Pozwalanie kodowi na obsługę integralności nie zawsze jest dobrym pomysłem. Dane są często wykorzystywane do podejmowania decyzji, ale jeśli są uszkodzone, decyzja nie będzie dokładna.
lepe
1
„Klucze obce są narzędziem integralności relacji” - prosimy o ostrożne używanie słowa „relacyjny”. Klucze obce to koncepcja bazy danych, krótka ręka dla ograniczenia integralności referencyjnej. Nie są częścią modelu relacyjnego. Zakładam, że popełniłeś literówkę.
kiedy
4

Najlepszym sposobem na wydajność jest używanie indeksów na często używanych polach. Jeśli używasz programu SQL Server, możesz użyć profilera do profilowania określonej bazy danych i pobrać plik, który wyprowadza, i użyć kreatora strojenia, aby otrzymać zalecenia dotyczące miejsca umieszczenia indeksów. Lubię też używać profilera do opróżniania długo działających procedur składowanych, mam listę dziesięciu najgorszych przestępców, którą publikuję co tydzień, aby ludzie byli uczciwi: D.

Al Katawazi
źródło
3

Możesz go użyć, aby zwiększyć wydajność zapytania. Pozwala to na restrukturyzację zapytań w SQL Server, aby używać sprzężenia zewnętrznego zamiast wewnętrznego, co eliminuje konieczność sprawdzania przez serwery sql, czy w kolumnie jest wartość null. Nie musisz umieszczać tego kwalifikatora, ponieważ relacja z kluczem obcym już to wymusza.

Więc to:

    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;

Staje się tym:

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;

Niekoniecznie zapewnia to dużą wydajność w przypadku małych zapytań, ale gdy tabele stają się duże, może być bardziej wydajne.

kemiller2002
źródło
3
Nie tylko łączenia zewnętrzne są zwykle mniej wydajne niż łączenia wewnętrzne ( stackoverflow.com/a/2726683/155892 ), ale teraz Twoje zapytania wprowadzają w błąd: polegasz na bazie danych, aby niejawnie przekształcić zewnętrzne sprzężenia w sprzężenia wewnętrzne (przywracanie wydajności) zamiast robić to wprost
Mark Sowul
2

W przypadku MySQL 5.7 z pewnością może zadziwiająco przyspieszyć zapytania obejmujące wielokrotne łączenia!

Użyłem „wyjaśnienia”, aby zrozumieć moje zapytanie i stwierdziłem, że dołączam do 4-5 tabel - w których nie używano żadnych kluczy. Nie zrobiłem nic, tylko dodałem klucz obcy do tych tabel, a wynikiem było 90% skrócenie czasu ładowania. Zapytania, które trwały dłużej niż 5 sekund, zajmują teraz 500 ms lub mniej.

To OGROMNA poprawa!

ORAZ, jak wspominali inni, otrzymujesz dodatkową premię w postaci zapewnienia integralności relacji.

Poza tym zapewnienie integralności referencyjnej ma również swoje zalety w zakresie wydajności. Efekt drugiego rzędu zapewnia, że ​​tabele z kluczem obcym są „aktualne” z tabelą obcą. Załóżmy, że masz tabelę użytkowników i tabelę komentarzy i robisz statystyki dotyczące tabeli komentarzy. Prawdopodobnie jeśli trwale usuniesz użytkownika, nie chcesz już też jego komentarzy.

Peter Bartlett
źródło
Czy tabele miały indeksy wymagane do wygenerowania kluczy obcych przed ich dodaniem?
George
1

Dodanie klucza obcego do tabeli nie poprawi wydajności, po prostu mówiąc, że jeśli wstawiasz rekord do bazy danych tabeli ProductCategories, spróbujesz znaleźć kolumnę klucza obcego o wartości istniejącej w wartości klucza podstawowego tabeli produktów, to wyszukiwanie, Operacja jest narzucona na bazę danych za każdym razem, gdy dodajesz nowy wpis w tabeli ProductCategories. Zatem dodanie klucza obcego nie poprawi wydajności bazy danych, ale zadba o integralność bazy danych. Tak, poprawi to wydajność twojej bazy danych, jeśli sprawdzasz integralność za pomocą klucza obcego zamiast uruchamiania wielu zapytań w celu sprawdzenia, czy rekord istnieje w bazie danych w twoim programie.

Pankaj Khairnar
źródło
0

Nie wiem zbyt wiele o serwerze SQL, ale w przypadku Oracle posiadanie kolumny klucza obcego zmniejsza wydajność ładowania danych. Dzieje się tak, ponieważ baza danych musi sprawdzać integralność danych dla każdej wstawki. I tak, jak już zostało wspomniane, posiadanie indeksu w kolumnie klucza obcego jest dobrą praktyką.

Shamik
źródło