2017-07-14 3 views
1

私はSQLレイアウトで参照を頻繁に使用していて、それが悪い習慣であるかどうか疑問に思っていました。 varchar(20)で参照を宣言すると、PostgreSQLはストレージの使用量を2倍にするか、隠しIDを使用して値をリンクしますか?参照のPostgreSQLストレージの必要性

例:

回または3回保存 distro値は
create table if not exists distros(
    name varchar(20), 
    primary key(name) 
); 

create table if not exists releases(
    distro varchar(20) references distros(name), 
    name varchar(20), 
    primary key(distro, name) 
); 

create table if not exists targets(
    distro varchar(20) references distros(name), 
    release varchar(20) references releases(name), 
    name varchar(20), 
    primary key (distro, release, name) 
); 

ですか?

ありがとうございました

+0

'targets'テーブルは' targets'の 'distro'カラムと' release'カラムの両方からなる 'releases'への外部キーを持っていなければなりません。 –

答えて

1

私はあなたのコラムdistroが1回または3回保存されているわけではないが、はるかに肯定的です。 それはあなたのテーブルのそれぞれにあります。しかしそれの上に、主キーの一部としてそれを作って、それをテーブルのために定義する各インデックスの一部にします。

このようにテーブルを作成します。それはあなたに多くのスペースを節約し、より速くなります。

create table if not exists distros(
    id serial, 
    name varchar(20), 
    primary key(id) 
); 

create table if not exists releases(
    id serial, 
    distro_id int references distros(id), 
    name varchar(20), 
    primary key(id) 
); 

create table if not exists targets(
    id serial, 
    distro_id int references distros(id), 
    release_id int references releases(id), 
    name varchar(20), 
    primary key (id) 
); 
+0

Postgresでは、 'id'カラムはシリアルデータ型でなければなりませんあなた自身でそれらを埋めることはしません。そして、この構造は必ずしもすべての用途でより速いわけではありません。たとえば、 'targets'テーブルからのみデータを選択し、ディストリビューター名を出力に含めるには、' distros'テーブルへの結合が必要ですが、自然キーが使用されていれば結合は必要ありません。また、与えられた構造体は 'releases'テーブルに存在しない' targets'テーブルのディストリビューションとリリースの組み合わせに対応することができます - おそらくデータ完全性エラーです。 –

+0

@rd_nielsen私はあなたが示唆したようにidデータ型の問題を修正しました。 OPは外部キーを使用するため、データの整合性が強制されます。そして、あなたは時には、id以外の何かを使う方が良いかもしれません。しかし、ほとんどの場合、そうではありません。 –

+0

ありがとうございます。レイアウトを変更します – pausiert

0

データが繰り返し表示されます。外部キーconstraint(a.k.a "references")を使用すると、参照された列に値が存在しない場合は、その列に値を入れることができません。

このtutorialは読む価値があります。

+0

IDを生成してテーブルを結合するビューを作成する方が良いでしょうか? – pausiert

+1

はい、IDのみが共通のデザインです – JGH

+0

現在のキーが整数よりもはるかに大きい場合は特に意味があります。そうでない場合(例: 'character(5)')、それは本当に必要ではありません。あなたが 'varchar(20)'を持っていればそれは意味があります。ほとんどの場合、20文字のうち3文字または4文字以上を使用します。 – joanolo

0

Postgresストレージのレイアウトはわかりませんが、各レコードをいわゆるデータページに完全に格納する必要があります。テーブルカン(インデックスを使用しない検索)の場合、追加の逆参照は不要です。すべての参照属性も含みます。 さらに、少なくとも部分的に各インデックスに格納されます。そこからは、使用しているインデックス技術に依存する、ある種のレコードIDを使用して参照レコードが見つかる場所に格納されます。通常のB(*)ツリーはこのように動作します。

したがって、答えは少なくとも3回、参照されたレコードを検索するために使用される各インデックスで一種の累積方法です。

関連する問題