2011-08-02 8 views
4

大きな既存のDBを継承しましたが、リファクタリングする必要があるかどうかを知りたいのですが、クエリの95%DBデザイン:テーブルまたは新しいテーブル内で制約を使用する必要があります

DBには、20行未満のID列と名前列しかない5つの表があります。私は著者がこれを行ったので、そこにある名前を変更して他のテーブルで変更することはできないと仮定しますが、それらのテーブルの多くは他のテーブルでのみ参照されます。これらの小さな2列のテーブルをより大きなテーブルにリファクタリングし、列に制約を追加すると、ユーザーは別のテーブルを持たずに間違った名前を入力できなくなりますか?

+3

に依存します。それらの結合は実際に高価なものですか(時間がかかる)ですか?しばしば、データ複製の量を最小限に抑えるために、データは非正規化される(したがって、結合を必要とする)。本当に遅い場合を除き、私には良いデザインのように聞こえます... –

答えて

8

抵抗する衝動。あなたの説明から、私は、既存の設計がしっかりしており、おそらく標準化されていると推測できます。 あなたのリファクタリングは実際には良いdb構造を元に戻すかもしれません。

質問に多くの結合を書き込むことに悩まされている場合は、定型文を緩和するためのビューを作成することをお勧めします。

彼が他のテーブルに にそれらを変更しないでそこに名前を変更することができるように...著者はこれをしなかった...

良いデザインの証拠であり、あなたがのために努力しなければならない、まさに正規化されたデータベースに保存します。

+2

Viewsに言及するために+1 - 彼らはあまり利用されていません:) –

3

いいえ。

あなたのデータベースは標準化されており、適切です。 を使用すると、スペース、検索時間、varcharではなくintを格納するための索引付けを省くことができます。

小さな表は適切にキーイングされていれば最適化されます。

1

あなたが持っているもののようなサウンドはルックアップテーブルです。 1つのテーブルにすべてのルックアップを追加して、それがどのタイプであるかを指定するために追加の列を追加することにしたときに起こります。 Fisrtでは、1つのクエリで4つの異なるテーブルに結合するのではなく、同じテーブルに4回結合する必要があります。 「すべてを支配する1つのテーブル」内のリソースの競合が増えてしまいます。さらに、あなたはFK制約を失います。つまり、最終的にデータの完全性が失われます。したがって、あるルックアップが状態の場合、customeraddressテーブルのstateidカラムに異なるタイプの顧客タイプのid値を設定することはできません。ルックアップが別々の場合は、その関係を強制します。

大きなテーブルの代わりに、顧客タイプの列に制約があるとします。制約が適用されるようになりましたが、変更が必要なときに問題があります。新しいタイプを追加するには、データベースを変更する必要があります。通常これはテーブルが大きくなったときに非常に悪い考えです。

1

ショートストーリー:文字列をID番号に置き換えることは、正規化とは関係ありません。あなたのケースで自然キーを使用すると、パフォーマンスが向上する可能性があります。 私のテストでは、ナチュラルキーを使用したクエリは1〜2桁速くなりました。

回答が早すぎる可能性があります。

DBには、IDと名前列のみがあり、 が20行未満の5つのテーブルがあります。

私はこれらのテーブルがこのような構造を持っていると仮定しています。

また、your_dataには少なくとも4つの結合が必要です(少なくとも使用可能な情報を得るには)。

ただし、表a、b、c、およびdの名前は一意(ahem)なので、一意の名前は外部キー参照のターゲットとして使用できます。 のようにテーブルyour_dataを書き直すことができます。

ID番号を文字列に置き換えても、通常のフォームは変更されません。 (文字列をID番号で置き換えることは、正規化とは関係ありません。)元のテーブルが5NFにあった場合、この書き換えは5NFにもなります。

パフォーマンスはどうですか? ID番号と結合が文字列より速いとは思われませんか?

私は、4つのテーブルa、b、c、dのそれぞれに20行を挿入することでテストしました。次に、ID番号で記述されたテストテーブルを1つ入力するデカルト積を生成し、名前を使用してデカルトテーブルを作成しました。 (それぞれ160K行)統計を更新し、いくつかのクエリを実行しました。

explain analyze 
select a.a_name, b.b_name, c.c_name, d.d_name 
from your_data_id 
inner join a on (a.a_id = your_data_id.a_id) 
inner join b on (b.b_id = your_data_id.b_id) 
inner join c on (c.c_id = your_data_id.c_id) 
inner join d on (d.d_id = your_data_id.d_id) 
... 
Total runtime: 808.472 ms 

explain analyze 
select a_name, b_name, c_name, d_name 
from your_data 
Total runtime: 132.098 ms 

ID番号を使用したクエリは実行に時間がかかります。 4つの列すべてにWHERE句を使用して、1つの行を返します。

explain analyze 
select a.a_name, b.b_name, c.c_name, d.d_name 
from your_data_id 
inner join a on (a.a_id = your_data_id.a_id and a.a_name = 'a one') 
inner join b on (b.b_id = your_data_id.b_id and b.b_name = 'b one') 
inner join c on (c.c_id = your_data_id.c_id and c.c_name = 'c one') 
inner join d on (d.d_id = your_data_id.d_id and d.d_name = 'd one) 
... 
Total runtime: 14.671 ms 

explain analyze 
select a_name, b_name, c_name, d_name 
from your_data 
where a_name = 'a one' and b_name = 'b one' and c_name = 'c one' and d_name = 'd one'; 
... 
Total runtime: 0.133 ms 

ID番号を使用するテーブルのクエリに約100倍の時間がかかりました。

使用されたテストPostgreSQL 9.something。

私のアドバイス:購入する前にお試しください。あなたが投資する前にテストしています。ナチュラルキーを使用するようにデータテーブルを書き直してみてください。慎重にON UPDATE CASCADEON DELETE CASCADEと考えてください。代表的なサンプルデータを使用してパフォーマンスをテストします。元の質問を編集し、見つけたものをお知らせください。

関連する問題