Day30 前半のゴール
「“頭の中の理解”を、“他人に渡せるアウトプット”に変える」
Day30 は、いよいよアウトプットの日です。 やることは3つ、「設計書」「ER図」「パフォーマンス改善レポート」。 前半では、それぞれを“何を書くものか”“どこまで書けば最低限OKか”を具体的に言語化していきます。
ゴールは、「完璧じゃなくていいから、チームメンバーに渡して意味が通じるレベルの3つの資料の“型”を作れること」です。
設計書とは何か
「“テーブル定義のメモ”ではなく、“なぜこう設計したか”を書くもの」
初心者がやりがちなのは、「設計書=テーブル定義のコピペ」と思ってしまうことです。 でも、本当に価値がある設計書は、「何を」「なぜ」こう設計したかが分かるものです。
設計書に最低限書きたいのは、次のような内容です。
システムの目的 どんなサービスを支えるDBなのか(例:小さなECサイトの顧客・注文管理)。
主要なエンティティ(テーブル)の役割 customers は「顧客の基本情報+柔軟な属性(JSONB)」を持つ。 products は「商品情報+属性(JSONB)」を持つ。 orders は「顧客に紐づく注文のヘッダ」で、状態や合計金額を持つ。 order_items は「注文に紐づく明細」で、商品・数量・単価を持つ。
設計の方針・ルール 金額は整数(○○cents)で持つ。 変化しやすい属性は JSONB に入れる。 注文時の単価は order_items.unit_price_cents にコピーして“履歴として固定”する。
ここで一番大事なのは、「未来の自分や他人が読んだときに、“ああ、だからこうなってるのか”と納得できる説明を書く」ことです。 SQLのCREATE TABLEは“結果”であって、“理由”は設計書に書きます。
設計書のミニ例
「Day29 のECスキーマを文章で説明してみる」
実際に、Day29 のスキーマの一部を設計書っぽく書いてみます。
システム概要 本システムは、小規模ECサイトの顧客管理・商品管理・注文管理・売上分析を行うためのデータベースである。顧客属性や商品属性、注文メタ情報など、変化しやすい情報を柔軟に扱うため、JSONBカラムを併用する。
テーブル:customers 顧客の基本情報を管理する。 主キーは id(bigserial)。 name は顧客名、email はログインや通知に使用するメールアドレスであり、一意制約を付与する。 created_at, updated_at は登録日時・更新日時を保持する。 extra_info は jsonb 型で、顧客の属性タグ(例:premium)、年齢レンジ、好みのカテゴリなど、将来的に増えうる情報を柔軟に格納する。
テーブル:orders 顧客ごとの注文ヘッダを管理する。 customer_id は customers.id への外部キーであり、「誰の注文か」を表す。 status は ‘pending’, ‘paid’, ‘shipped’, ‘cancelled’ などの状態を文字列で保持する。 total_cents は注文全体の金額(税・送料込み)を整数で保持する。 meta は jsonb 型で、支払い方法、クーポン情報、配送メモなど、注文ごとに異なるメタ情報を格納する。
このくらい書けると、「SQLを見なくても、だいたい何をしたいDBか」が伝わります。 Day30 前半では、この“文章で説明する力”を意識してほしいです。
ER図とは何か
「“テーブルの箱”と“線”で、関係性を一発で見せる図」
ER図(Entity-Relationship 図)は、「テーブル同士の関係を図で表したもの」です。 コードや設計書が“言葉”だとしたら、ER図は“地図”です。
基本の要素はシンプルです。
エンティティ(Entity) テーブルに相当する箱。例:customers, products, orders, order_items。
リレーションシップ(Relationship) テーブル同士の関係を表す線。例:customers 1 対多 orders、orders 1 対多 order_items、products 1 対多 order_items。
カーディナリティ 「1対多」「多対多」「1対1」などの関係性。 今回のECスキーマでは、 顧客1人に対して、注文が複数(1対多)。 注文1件に対して、明細が複数(1対多)。 商品1つに対して、複数の明細から参照される(1対多)。
ER図の目的は、「このDBがどんな“世界”を表しているかを、一目で分かるようにすること」です。 SQLを知らない人(ビジネス側)にも、「顧客と注文がこうつながっているのね」と伝えられるのが理想です。
Day29 スキーマのER図を頭の中で描いてみる
「箱と線だけでいいから、関係を言語化する」
実際に図はここでは描けないので、「言葉でER図を説明する」練習をしてみます。
エンティティ customers(顧客) products(商品) orders(注文ヘッダ) order_items(注文明細)
リレーションシップ customers と orders は 1対多。 1人の顧客は複数の注文を持てる。 1つの注文は必ず1人の顧客に属する。
orders と order_items は 1対多。 1つの注文には複数の明細がぶら下がる。 1つの明細は必ず1つの注文に属する。
products と order_items は 1対多。 1つの商品は、複数の注文明細から参照される。 1つの明細は必ず1つの商品を指す。
この関係を図にすると、 customers → orders → order_items → products という“線の流れ”が見えてきます。
ここでの大事なポイントは、「ER図は“テーブルの数やカラム数”ではなく、“関係の構造”を見るためのもの」ということです。 Day30 前半では、「自分のスキーマをER図として説明できるか」を意識してみてください。
パフォーマンス改善レポートとは何か
「“なんとなく速くした”ではなく、“測って、変えて、また測った”記録」
最後に、「パフォーマンス改善レポート」です。 これは、「どこが遅かったのか」「何を変えたのか」「どれくらい良くなったのか」をまとめたドキュメントです。
ただ「インデックスを張りました」ではなく、次の3点を書くのが重要です。
現状の問題の把握 どのクエリが遅いのか。 どの画面・機能で体感的な遅さが出ているのか。 EXPLAIN / EXPLAIN ANALYZE の結果はどうなっているか。
改善内容 どのカラムにどんなインデックスを張ったか。 クエリを書き換えたか(不要なJOINを減らした、WHERE条件を変えたなど)。 テーブル設計を変えたか(正規化/非正規化、集計テーブルの追加など)。
改善結果 改善前と改善後で、実行時間がどう変わったか(ms単位で書く)。 CPU使用率やI/Oがどう変わったか(分かる範囲で)。 副作用(INSERTが少し遅くなったが、SELECTが大幅に速くなった、など)。
これを書くことで、「なぜこのインデックスがあるのか」「なぜこのクエリはこう書かれているのか」が未来の自分にも伝わります。 パフォーマンス改善は“その場のチューニング”ではなく、“チームの知識資産”にするのが理想です。
パフォーマンス改善レポートのミニ例
「JSONBフィルタを速くした、というケースを書いてみる」
Day29 の「premium顧客だけの売上集計」が遅くなってきた、という想定で、ミニレポートを書いてみます。
現状の問題 クエリ: premiumタグが付いている顧客の売上合計を集計するクエリ(customers.extra_info -> ‘tags’ ? ‘premium’ を使用)。 データ量:customers 約50万件、orders 約200万件。 問題:ピーク時にこのクエリが数十秒かかり、管理画面の表示が遅くなっている。EXPLAIN ANALYZE の結果、customers テーブルがシーケンシャルスキャンになっている。
改善内容 customers.extra_info に対して GIN インデックスを追加。 SQL: CREATE INDEX idx_customers_extra_info_gin ON customers USING GIN (extra_info);
改善結果 インデックス作成後、同じクエリの実行時間が約30秒 → 約300ms に短縮。 EXPLAIN ANALYZE で、customers のアクセスが GIN インデックススキャンに変わっていることを確認。 副作用として、customers へのINSERT/UPDATE時にインデックス更新コストが増えるが、顧客登録・更新の頻度は低いため許容範囲と判断。
このくらい書けると、「なぜこのGINインデックスがあるのか」が一目で分かります。 Day30 前半では、「こういうレポートを自分でも書けそうだ」という感覚を持てれば十分です。
Day30 前半のまとめ
Day30 前半では、「設計書=テーブル定義の羅列ではなく、“このDBは何のためにあり、各テーブルがどんな役割と設計方針を持っているか”を文章で説明するもの」「ER図=customers/orders/order_items/products のようなエンティティ同士の“1対多”などの関係を箱と線で一目で示す地図」「パフォーマンス改善レポート=どのクエリが遅くて、何を変えて、どれくらい速くなったかをEXPLAINの結果や実行時間と一緒に残す記録」であり、これら3つを作ることで、“自分の頭の中の理解”を“他人に渡せる形”に変えられる、という位置づけを掴むことがDay30 前半のゴールになる。
