2

ファイルとメモを顧客、ユーザー、プロジェクトなどにリンクするWebアプリがあります。最初は、customerNote、userNote、projectNote...などのテーブルがありました。

設計上の考慮事項:
1:N個の2乗テーブル(100を超えるcustomerNote、userNote、projectNote、... customerFile、projectFile ... etcテーブル)を管理
したくない2:動的SQL(TableName from LinkType)
3:リンクテーブルを使用するクリーンな方法がわかりません(100以上のNの2乗リンクテーブルなし)

これで、LinkIdとLinkTypeIdを持つNoteテーブルが1つあります。LinkIdはもちろん、client | User | Project|etcテーブルのPKです。LinkTypeIdは、リンクのタイプを指します。

したがって、この:
SELECT * FROM customerNote WHERE Id = 1210
SELECT * FROM userNote WHERE Id = 3281

現在は次のようになっています:
SELECT * FROM Note WHERE LinkId = 1210 AND LinkTypeId = 2(2は顧客)
SELECT * FROM Note WHERE LinkId = 3281 AND LinkTypeId = 3(3はユーザー)

私はこのアプローチの単純さを楽しんでおり、それらを私が至る所で呼び出す関数にラップしています。

私の質問は次のとおりです
。1:参照整合性がないと、どのようなパフォーマンスやその他の問題が発生しますか?
2:これはスケーラビリティの問題を引き起こしますか?
3:エレガントな解決策はありますか?

これは私の最初のSO投稿であり、皆さんの助けに前もって感謝します。

4

1 に答える 1

1

1:参照整合性がなければ、どのようなパフォーマンスやその他の問題が発生しますか?

参照整合性が排除しようとしているすべての問題が発生する可能性があります。これらの問題に対処するか、アプリケーションコードまたは管理手順(レポートなど)を通じてすべての参照整合性制約の模倣を実装する必要があります。

また、「メモ」テーブルのサイズも大幅に大きくなります。自由形式のメモの100のテーブルのそれぞれの10万行はかなり扱いやすいです。しかし、1つのメモの表に1,000万行あると、人生が生きる価値があるかどうかを再考する可能性があります。

アプリケーションコードに整合性制約の模倣を実装するということは、遅かれ早かれ、誰か(おそらくあなた)がアプリケーションを回避し、dbmsコマンドラインクライアントまたはGUIクライアントを介して行を変更することを意味します。そうすれば多くのダメージを与えることができます。そのようなリスクを冒す前にデータベースをチェックポイントまたはダンプするのが正しいことですが、1,000万行のメモがあると、そうする可能性が低くなります。

2:これはスケーラビリティの問題を引き起こしますか?

できる。100個の個別のノートテーブルがある場合、それぞれが100,000行に拡大しても、クエリを高速に実行できます。それらすべてを1つのテーブルに入れると、1,000万行になります。また、メモであるため、ページに収まるものは少なくなります。これは通常、速度が遅いことを意味します。この設計では、メモの1つのテーブルがコールドスポット(または、見方によってはホットスポット)になり、 1つまたは2つの大きな注釈が付けられたテーブルだけでなく、メモを使用するすべてのテーブルの速度が低下します。

そして、すべてのテーブルで2、3か月間低速で生活した後、そのモンスターテーブルを元のテーブルに再び分割する可能性があります。

3:エレガントな解決策はありますか?

すべてのノートの最大長が同じであると想定される場合(100ノートテーブルの要件はほとんどありません)、ノートのドメインを作成し、注釈付きテーブルごとに1つのノートテーブルを作成します。

create domain note_text as varchar(1000) not null;
create table user_notes (
  user_id integer not null references users (user_id) on delete cascade,
  note_timestamp timestamp not null default current_timestamp,
  user_note note_text,
  primary key (user_id, note_timestamp)
);

余談ですが、ユーザーが行に注釈を付けられるように注意する必要があります。彼らはしばしば(通常?)それが属する場所にデータを置く代わりにメモ列を使用します。たとえば、ユーザーの電話番号のテーブルがある場合、メモの列はほぼ確実にこれでデータ行になります。

Call 123-456-7890 between 8:00 am and 5:00 pm. (And that will match 
   none of this user's phone numbers.)
Toll-free orders at 1-800-123-4567.
He eats lunch at McDonald's on Tuesdays.
于 2012-03-07T00:19:07.893 に答える