Wolałbym drugie podejście. Używając zastępczych numerów identyfikacyjnych, gdy nie są one logicznie niezbędne do identyfikacji, wprowadzasz więcej obowiązkowych sprzężeń. Wymaga to „ścigania numerów identyfikacyjnych w całej bazie danych”, co jest odpowiednikiem SQL do „ścigania wskaźników po całej bazie danych”. Pogoń za wskaźnikami była charakterystyczna dla IMS, jednej z architektur baz danych, którą model relacyjny zamierzał zastąpić. (IMS wykorzystuje architekturę hierarchiczną.) Dziś nie ma sensu wymyślać tego na nowo. (Chociaż dużo ludzi właśnie to robi.)
Jeśli masz na przykład pięć poziomów zastępczych numerów identyfikacyjnych i chcesz podać imię osoby, musisz wykonać cztery łączenia, aby je uzyskać. Korzystając z drugiego podejścia, potrzebujesz tylko jednego połączenia. Jeśli nie chcesz pisać złączeń wielokolumnowych, użyj CREATE VIEW i zrób to tylko raz.
Wydajność można łatwo przetestować . Po prostu wygeneruj kilka milionów losowych wierszy przy użyciu swojego ulubionego języka skryptowego i załaduj je na serwer testowy. Nie tylko dowiesz się, gdzie kryją się Twoje problemy z wydajnością, ale znajdziesz wszystkie błędy w kodzie CREATE TABLE. (Twój kod nie będzie działał tak, jak jest.) Dowiedz się więcej o WYJAŚNIJ jeśli jeszcze o tym nie wiesz.
Co do indeksowania , możesz to przetestować na losowo generowanych i ładowanych wierszach. Indeks wielokolumnowy (imię, nazwisko) będzie działał najlepiej, jeśli użytkownicy zawsze podają imię. Ale wielu użytkowników tego nie zrobi, woląc zamiast tego wyszukiwać według nazwiska. Indeks wielokolumnowy na (imię, nazwisko) nie jest skuteczny w przypadku użytkowników, którzy wolą wyszukiwać według nazwiska. Możesz to przetestować.
Tylko z tego powodu indeksowanie imion i nazwisk jest zazwyczaj bardziej efektywne, jeśli istnieją dwa oddzielne indeksy, jeden dla imienia, a drugi dla nazwiska.
Co oznacza wyszukiwanie numerów identyfikacyjnych znaczy?
Niewypowiedziany wzorzec projektowy leżący u podstaw tego pytania to „Każdy wiersz musi mieć numer identyfikacyjny, a wszystkie klucze obce muszą odwoływać się do numeru identyfikacyjnego”. W bazie danych SQL jest to właściwie antywzorzec. Zasadniczo każdy wzorzec, który pozwala projektować tabele bez myślenia o klawiszach, powinien być uznawany za winny, dopóki nie zostanie udowodniony jego niewinność — należy zakładać, że jest antywzorcem, dopóki nie zostanie udowodnione, że tak nie jest.
create table A (
a_id integer primary key,
a_1 varchar(15) not null unique,
a_2 varchar(15) not null
);
create table B (
b_id integer primary key
a_id integer not null references A (a_id),
b_1 varchar(10) not null,
unique (a_id, b_1),
);
create table C (
c_id integer primary key,
b_id integer not null references B (b_id),
c_1 char(3) not null,
c_2 varchar(20) not null,
unique (b_id, c_1)
);
create table D (
d_id integer primary key,
c_id integer not null references C (c_id),
d_1 integer not null,
d_2 varchar(15),
unique (c_id, d_1)
);
Jeśli potrzebujesz raportu na temat tabeli „D”, a raport wymaga
- kolumny D.d_1 i D.d_2 oraz
- kolumny A.a_1 i A.a_2,
potrzebujesz 3 złączeń, aby się do tego dostać. (Spróbuj.) Gonisz numery identyfikacyjne. (Jak gonienie wskaźników w IMS.) Poniższa struktura jest inna.
create table A (
a_1 varchar(15) primary key,
a_2 varchar(15) not null
);
create table B (
a_1 varchar(15) not null references A (a_1),
b_1 varchar(10) not null,
primary key (a_1, b_1),
);
create table C (
a_1 varchar(15) not null,
b_1 varchar(10) not null,
c_1 char(3) not null,
c_2 varchar(20) not null,
primary key (a_1, b_1, c_1),
foreign key (a_1, b_1) references B (a_1, b_1)
);
create table D (
a_1 varchar(15) not null,
b_1 varchar(10) not null,
c_1 char(3) not null,
d_1 integer not null,
d_2 varchar(15),
primary key (a_1, b_1, c_1, d_1),
foreign key (a_1, b_1, c_1) references C (a_1, b_1, c_1)
);
Przy tej strukturze ten sam raport wymaga pojedynczego połączenia.
select D.d_1, D.d_2, A.a_1, A.a_2
from D
inner join A on D.a_1 = A.a_1;