私は2番目のアプローチを好みます。識別に論理的に必要でない場合に代理ID番号を使用することにより、より必須の結合を導入します。これには、「データベース全体でID番号を追跡する」必要があります。これは、「データベース全体でポインターを追跡する」と同等のSQLです。ポインタの追跡は、リレーショナルモデルが置き換えることを目的としたデータベースアーキテクチャの1つであるIMSの特徴でした。 (IMSは階層アーキテクチャを使用しています。)今日、それを再発明する意味はありません。 (ただし、ロット まさにそれをする人の数です。)
たとえば、5つのレベルの代理ID番号があり、人の名前が必要な場合は、それを取得するために4つの結合を行う必要があります。 2番目のアプローチを使用すると、必要な結合は1つだけです。複数列の結合を記述したくない場合は、CREATEVIEWを使用して1回だけ実行してください。
パフォーマンスのテストは簡単です 。お気に入りのスクリプト言語を使用して数百万のランダムな行を生成し、それらをテストサーバーにロードするだけです。パフォーマンスの問題が隠れている場所を見つけるだけでなく、CREATETABLEコードのすべてのエラーを見つけることができます。 (コードはそのままでは機能しません。)EXPLAINについて学ぶ まだ知らない場合は
インデックス作成について 、生成してロードするランダムな行でそれをテストできます。 (first_name、last_name)の複数列のインデックスは、ユーザーが常に名を指定する場合に最適に機能します。しかし、多くのユーザーはそれを行わず、代わりに姓で検索することを好みます。 (first_name、last_name)の複数列のインデックスは、姓で検索することを好むユーザーには効果的ではありません。あなたはそれをテストすることができます。
その理由だけで、名と名前のインデックス付けは通常です。 1つは名用、もう1つは姓用の2つの別個のインデックスがある場合、より効果的です。
ID番号の追跡 意味?
この質問の根底にある暗黙のデザインパターンは、「すべての行にID番号が必要であり、すべての外部キーがID番号を参照する必要がある」というものです。 SQLデータベースでは、これは実際にはアンチパターンです。経験則として、キーについて考えずにテーブルを設計できるパターンは、無罪であることが証明されるまでは有罪であると推定されるべきです。そうでないことが証明されるまでは、アンチパターンであると推定されるべきです。
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)
);
テーブル「D」のレポートが必要で、レポートが必要な場合
- 列D.d_1とD.d_2、および
- 列A.a_1およびA.a_2、
それに到達するには3つの結合が必要です。 (試してみてください。)ID番号を追いかけています。 (IMSでポインターを追跡するように。)次の構造は異なります。
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)
);
この構造では、同じレポートに1つの結合が必要です。
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;