Preferoval bych druhý přístup. Použitím náhradních identifikačních čísel, když nejsou logicky nezbytná pro identifikaci, zavádíte více povinných spojení. To vyžaduje, abyste „pronásledovali ID čísla po celé databázi“, což je ekvivalent SQL k „sledování ukazatelů po celé databázi“. Chasing pointers byl charakteristický pro IMS, jednu z databázových architektur, kterou měl relační model nahradit. (IMS používá hierarchickou architekturu.) Dnes nemá smysl ji znovu objevovat. (I když hodně lidí to dělá.)
Pokud máte například pět úrovní náhradních identifikačních čísel a chcete jméno osoby, musíte provést čtyři spojení, abyste je získali. Při použití druhého přístupu vám stačí jedno spojení. Pokud nechcete psát spojení s více sloupci, použijte CREATE VIEW a udělejte to jen jednou.
Testování výkonu je snadné . Stačí vygenerovat několik milionů náhodných řádků pomocí vašeho oblíbeného skriptovacího jazyka a nahrát je na testovací server. Nejenže zjistíte, kde se skrývají vaše problémy s výkonem, najdete všechny chyby v kódu CREATE TABLE. (Váš kód nebude fungovat tak, jak je.) Další informace o EXPLAIN pokud o tom ještě nevíte.
Pokud jde o indexování , můžete to otestovat na náhodných řádcích, které vygenerujete a načtete. Vícesloupcový index na (first_name, last_name) bude fungovat nejlépe, pokud uživatelé vždy uvádějí křestní jméno. Spousta uživatelů to ale neudělá a raději budou hledat podle příjmení. Vícesloupcový index na (first_name, last_name) není účinný pro uživatele, kteří dávají přednost vyhledávání podle příjmení. Můžete to otestovat.
Už jen z tohoto důvodu je indexování křestních jmen a příjmení obvykle efektivnější, pokud existují dva samostatné indexy, jeden pro křestní jméno a jeden pro příjmení.
Co znamená shánění identifikačních čísel znamenat?
Nevyslovený návrhový vzor, který je základem této otázky, je "Každý řádek musí mít identifikační číslo a všechny cizí klíče musí odkazovat na identifikační číslo." V SQL databázi je to vlastně anti-vzor. Obecně platí, že každý vzor, který vám umožní navrhovat tabulky bez přemýšlení o klíčích, by měl být považován za vinný, dokud se neprokáže nevina – měl by být považován za anti-vzor, dokud se neprokáže, že tomu tak není.
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)
);
Pokud potřebujete zprávu o tabulce "D", a zpráva potřebuje
- sloupce D.d_1 a D.d_2 a
- sloupce A.a_1 a A.a_2,
k tomu potřebujete 3 spojení. (Zkuste to.) Honíte se za identifikačními čísly. (Jako chasing pointers v IMS.) Následující struktura je odlišná.
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)
);
S touto strukturou potřebuje stejná sestava jediné spojení.
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;