完成と次のステップ
設計は書き残して初めて残る
最後のレッスンです。頭の中にある設計は、引き継いだ瞬間に消えます。設計書として1枚にまとめておくと、半年後の自分と次の担当者が助かります。
書くのは次の4つだけで足ります。
| 項目 | 中身 |
|---|---|
| ER図 | 実体と関係、多重度 |
| テーブル定義 | 列・型・NOT NULL・既定値 |
| 制約一覧 | 何を守っているか、業務ルールとの対応 |
| 索引一覧 | どのクエリのための索引か |
特に大事なのが右の列です。何のためにあるのかが書かれていない設計書は、直すときに誰も手を出せません。「消してよいのか分からない索引」は、こうして生まれます。
完成したもの
このコースで、多店舗ECのデータベースを一通り設計しました。
第1章で要件からエンティティを取り出し、第2章で ER図に描き、第3章で正規化して重複を無くし、第4章でキーと制約を決め、第5章で名前と型を確定させ、第6章で索引を設計しました。第7章では新しい要件を独力で通しました。
この順番そのものが成果物です。次に新しい要件を受け取ったときも、同じ順で進められます。
この先に続くもの
設計の基礎はここまでです。実務で次にぶつかるのは、たいてい次の3つです。
トランザクションと同時実行。 複数の処理が同時に同じ行を触るときに、何が起きるかを決める仕組みです。在庫の引き当てや残高の更新で必ず必要になります。
マイグレーション。 動いているシステムのテーブルを、止めずに変える方法です。列を足すのは簡単ですが、型を変える、テーブルを分ける、という変更には手順があります。
スケール。 行数が億に届いたとき、1台では足りなくなります。パーティションやレプリケーションの話に入ります。
どれも、正しく設計されたデータベースの上でしか成立しません。土台はもうできています。
手を動かす
完成した設計の全体像を、1本のクエリで書き出します。
テーブル構造
CREATE TABLE customers (
id integer PRIMARY KEY,
name text NOT NULL,
email text NOT NULL,
CONSTRAINT customers_email_uk UNIQUE (email)
);
CREATE TABLE products (
id integer PRIMARY KEY,
name text NOT NULL,
price integer NOT NULL,
CONSTRAINT products_price_ck CHECK (price > 0)
);
CREATE TABLE orders (
id integer PRIMARY KEY,
customer_id integer NOT NULL REFERENCES customers (id),
ordered_on date NOT NULL,
total integer NOT NULL
);
CREATE TABLE order_items (
order_id integer NOT NULL REFERENCES orders (id),
product_id integer NOT NULL REFERENCES products (id),
quantity integer NOT NULL,
unit_price integer NOT NULL,
PRIMARY KEY (order_id, product_id),
CONSTRAINT order_items_qty_ck CHECK (quantity > 0)
);
CREATE TABLE coupons (
id integer PRIMARY KEY,
code text NOT NULL,
discount_amount integer NOT NULL,
expires_on date NOT NULL,
CONSTRAINT coupons_code_uk UNIQUE (code),
CONSTRAINT coupons_discount_ck CHECK (discount_amount > 0)
);
CREATE TABLE coupon_usages (
id integer PRIMARY KEY,
coupon_id integer NOT NULL REFERENCES coupons (id),
order_id integer NOT NULL REFERENCES orders (id),
customer_id integer NOT NULL REFERENCES customers (id),
discounted_amount integer NOT NULL,
CONSTRAINT coupon_usages_order_uk UNIQUE (order_id),
CONSTRAINT coupon_usages_customer_uk UNIQUE (coupon_id, customer_id)
);
CREATE TABLE reviews (
id integer PRIMARY KEY,
product_id integer NOT NULL REFERENCES products (id),
customer_id integer NOT NULL REFERENCES customers (id),
rating integer NOT NULL,
body text NOT NULL,
CONSTRAINT reviews_rating_ck CHECK (rating BETWEEN 1 AND 5),
CONSTRAINT reviews_product_customer_uk UNIQUE (product_id, customer_id)
);
CREATE INDEX coupon_usages_customer_id_idx ON coupon_usages (customer_id);
CREATE INDEX coupons_expires_on_idx ON coupons (expires_on);
CREATE INDEX reviews_customer_id_idx ON reviews (customer_id);
期待される出力
| table_count | constraint_count | index_count |
|---|---|---|
| 7 | 24 | 16 |