0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SQLアンチパターン:DB論理設計のアンチパターン

Last updated at Posted at 2022-05-12

はじめに

有名なあの本を読んだ備忘録です。
ありふれた内容ですが、こんな記事いくらあってもいいですからね!

1章 ジェイウォーク(信号無視)

概要

一つの列に複数の値をもたせるのはやめましょう。

product_id product_name account_id
1 table 123, 456
2 chair 456, 789

対策

交差テーブルを作りましょう。
スクリーンショット 2022-05-12 16.00.40.png

2章 ナイーブツリ-(素朴な木)

別途

3章 IDリクアイアド(とりあえずID)

概要

主キー名はわかりやすく命名しましょう。
また、必ずしもid列は必要ありません。

対策

例えば、交差テーブルの主キーは複合キーをつかう。

create table Contacts (
  product_id bigint unsigned not null,
  account_id bigint unsigned not null,
  foreign key (product_id) references Products(product_id),
  foreign key (account_id) references Accounts(account_id),
  primary key (product_id, account_id)
);

4章 キーレスエントリ(外部キー嫌い)

概要

外部キー制約を使って参照整合性を担保しましょう。
キーレスエントリでは柔軟性が高まりますが、さまざまな代償が伴います。

5章 EAV (Entity Attribute Value)

概要

汎用的な属性テーブルを使用するのはやめましょう。

issue_id attr_name attr_value
1 severity 5
2 sponsor example_inc
3 status NEW

対策

  • 半構造化データに対してはNoSQLを使いましょう
  • 例えば下記のようなサブタイプのモデリングを行いましょう

「クラステーブル継承」の例

BugsFeatureRequestIssuesを継承しています。
スクリーンショット 2022-05-12 16.00.49.png

メモ

blob, clob, text型などをLOB(Large Object)という。
処理が重くなりがちなので基本避ける。
Jsonなどの半構造化データはこの型をつかう。

6章 ポリモーフィック関連

概要

一つのエンティティに対して、複数の親を設定するのはやめましょう。
2つ以上の親に対して外部キーを設定できないからです。
スクリーンショット 2022-05-12 19.50.45.png

対策

  • 交差テーブルの作成
    スクリーンショット 2022-05-12 19.59.33.png

  • 共通の親テーブルの作成
    スクリーンショット 2022-05-12 20.07.37.png

7章 マルチカラムアトリビュート (複数列属性)

概要

複数の列を定義するのはやめましょう。

product_id product_name  tag1 tag2 tag3
1 table white NULL NULL
2 chair NULL long NULL
3 paper NULL NULL 100

対策

従属テーブルを作成する。
上の例で言うと、tagを新たなテーブルとして作成し、productテーブルから参照させます。

8章 メタデータドリブル(メタデータ大増殖)

概要

スケーラビリティを求めて、内容の同じテーブルや列をコピーするのはやめましょう。

create table Bugs_2008 (...);
create table Bugs_2009 (...);
create table Bugs_2010 (...);

対策

  • 水平パーティショニング
    DBエンジンのパーティション機能を使う。
    テーブルは物理的に分割されているが、あたかも1つのテーブルかのようにSQLステートメントを実行できる。
create table Bugs (
  bug_id serial primary key,
  ...,
  date_reported DATE
) partition by hash (year (date_reported))
  partitions 4;
  • 垂直パーティショニング
    列でテーブルを分割できる。1部の列がサイズが大きい場合や、滅多に使用されない場合に活用できる。
    例えば、BLOB列とTEXT列はサイズ可変で、通常は非常に大きいサイズであることが考えられる。
    これらの列を分割して保存することで、他の列に効率的にアクセスできる。
    クエリの際の列名に*を使わないように注意。

  • 従属テーブルの導入
    概要の例でいうと、プロジェクトごとに年別の列を持たせる代わりに、プロジェクトと年の組み合わせが1行となる従属テーブルを新たに定義しましょう。

create table ProjectHistory (
  project_id bigint,
  year smallint,
  primary key (project_id, year)
  foreign key (project_id) references Projects(project_id)
);

おわりに

まだまだ続きます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?