Jag föredrar det andra tillvägagångssättet. Genom att använda surrogat-ID-nummer när de inte är logiskt nödvändiga för identifiering introducerar du fler obligatoriska anslutningar. Detta kräver att du "jagar ID-nummer över hela databasen", vilket är SQL-motsvarigheten till "jaga pekare över hela databasen". Att jaga pekare var karakteristiskt för IMS, en av de databasarkitekturer som relationsmodellen tänkt ersätta. (IMS använder en hierarkisk arkitektur.) Det är ingen idé att återuppfinna den idag. (Även om det är mycket av människor gör just det.)
Om du till exempel har fem nivåer av surrogat-ID-nummer, och du vill ha en persons namn, måste du göra fyra joins för att få det. Med den andra metoden behöver du bara en koppling. Om du inte vill skriva sammanfogningar med flera kolumner, använd CREATE VIEW och gör det bara en gång.
Prestandan är enkel att testa . Skapa bara några miljoner slumpmässiga rader med ditt favoritskriptspråk och ladda dem till en testserver. Du hittar inte bara var dina prestandaproblem gömmer sig, du hittar alla fel i din CREATE TABLE-kod. (Din kod kommer inte att fungera som den är.) Läs mer om EXPLAIN om du inte redan vet om det.
När det gäller indexering , du kan testa det på de slumpmässiga raderna du genererar och laddar. Ett index med flera kolumner på (förnamn, efternamn) fungerar bäst om användare alltid anger ett förnamn. Men många användare kommer inte att göra det, de föredrar att söka på efternamn istället. Ett index med flera kolumner på (first_name, last_name) är inte effektivt för användare som föredrar att söka på efternamn. Du kan testa det.
Bara av den anledningen är indexering av förnamn och efternamn vanligtvis effektivare om det finns två separata index, ett för förnamnet och ett för efternamnet.
Vad innebär chasing id-nummer menar?
Det outtalade designmönstret som ligger till grund för denna fråga är "Varje rad måste ha ett ID-nummer, och alla främmande nycklar måste referera till ID-numret." I en SQL-databas är det faktiskt ett antimönster. Som en tumregel bör alla mönster som låter dig designa tabeller utan att tänka på nycklar antas vara skyldiga tills det har bevisats oskyldigt – det bör antas vara ett antimönster tills det har bevisats att det inte är det.
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)
);
Om du behöver en rapport på tabell "D", och rapporten behöver
- kolumnerna D.d_1 och D.d_2, och
- kolumnerna A.a_1 och A.a_2,
du behöver 3 joins för att komma till det. (Prova.) Du jagar ID-nummer. (Som att jaga pekare i IMS.) Följande struktur är annorlunda.
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)
);
Med den här strukturen behöver samma rapport en enda sammanfogning.
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;