ER図を考え直してみた

Namiki Chikusa
SENDAI事業部 プロダクトCTO
初めまして。 株式会社STARUPでアパレル業界向けAIプラットフォーム「SENDAI」のプロダクトCTOを務めています、千種です。
ER図が読めなくなった
最初のうちはER図をきちんと描いていたのに、システムが大きくなるにつれて更新が追いつかなくなり、いつの間にか、どんなテーブルがあるのかさえ分からなくなっている。 そんな経験はないでしょうか?
私が開発しているSENDAIも、テーブルが数十個のうちは何も問題がありませんでした。 ER図は見やすく、同じ図が頭の中にも入っていました。テーブルを追加するときも、図のどこに置くかで迷うことはありませんでした。
状況が変わったのは、Claude CodeやCodexといったAIツールに実装を任せるようになってからです。 AIの実装スピードに把握が追いつかず、自分がイメージしているDB構造と実際のスキーマが乖離するようになりました。「あれ、こんなテーブルいつ作ったっけ?」とAIへ聞き返す場面に覚えがある方も多いんじゃないでしょうか。
テーブル数が100を超えたあたりで、ER図の側も限界でした。 テーブルが増えるにつれてリレーションの矢印は交錯し、全体感は掴めず、新しいテーブルをどこに描き足すべきかも決められません。 レイアウトを整え直しても、次の追加でまた崩れます。
そうなると、そもそもER図はなんのために書いているのかという問いに立ち返ります。
ER図は何のために書くのか
ER図の用途は、大きく2つに分かれます。
- 全体の把握:どんなテーブルがあり、互いにどう関係しているかを掴む
- 個別の把握:あるテーブルのカラムや型、制約を確認する
ステークホルダーへの説明も新メンバーのオンボーディングも、突き詰めればこの2つのどちらかに帰着します。
問題は、2つの目的が要求する情報はまるで違うことです。 全体を把握したいとき、必要なのはテーブル名とリレーションだけで、カラムは1つも要りません。 個別のテーブルを確認したいとき、必要なのはそのテーブルと直接関係するテーブルだけで、残る100近いテーブルは視界に入らなくていいはずです。
しかし、従来のER図はこの2つを一枚に同居させています。 カラムを書くとボックスが縦に伸び、図の面積が広がり、リレーションの線は長くなって交錯します。 個別の把握のための情報が、全体の把握のための情報を物理的に潰しているわけです。
地図にたとえるなら、県境を確かめたい地図に、全部の家の表札が描き込まれているようなものです。
分ける、という発想
であれば、分ければいいはずです。
典型的なカラム込みのER図はこんな感じです。
※ 以下は架空のAIプロダクトのスキーマです。

たった14テーブルでこれです。 ボックスが縦に伸びる分だけ図の面積が広がり、リレーションの線を目で追うのがすでに苦しくなっています。
ここから、カラムを全部消してみます。

同じ14テーブルが、ボックス名だけで一望できます。
ただ、これだけでは個別の把握ができません。 カラムを見たくなるたびにスキーマ定義ファイルを開きにいくのでは、図を分けた意味が半減します。 全体図から気になったテーブルのカラムをその場で確認でき、リレーションも追える仕組みが要ります。 そこで次のようなビューワーを作りました。
super ER diagram(仮)
作ったのは、ブラウザだけで動く静的なスキーマビューワです。 私はこれを**super ER diagram(仮)**と呼んでいます。OSSとして公開しています。
以下は架空のスキーマを使ったデモです。ぜひ、「全画面で開く」で試してみてください。
画面は3つの領域でできています。
- 中央のER図:テーブル名だけの小さなボックスとFKの矢印で構成した全体図である。
- 右の詳細パネル:ボックスをクリックすると、そのテーブルのカラム・型・FK・一行説明が出る。パネル内のFKリンクで隣のテーブルへ移動できる。
- 左のツリーと検索:ドメイン別のテーブル一覧と検索ボックスである。
たとえばprojectsをクリックすると、左右のパネルにはこう出ます。

全体の把握は中央の図が、個別の把握は右のパネルが受け持ちます。 2つの目的は同じ画面に共存していますが、同じ図には同居していません。 カラムは「描くもの」から「クリックしたときだけ出てくるもの」になりました。
読みやすさのための四つの工夫
カラムを消すだけでは足りません。矢印はまだ多く、名前だけのボックスだと今度は情報が薄すぎます。
1つめの工夫は、テナントスコープのFKを矢印として描かないことです。 マルチテナントのシステムでは、organization_idのようなカラムがほぼすべてのテーブルに生えています。 これを律儀に描くと、図はテナントテーブルを中心とした放射状の毛玉のようになります。 そこで、こうしたFKは矢印を省略し、詳細パネルの中のリンクとしてだけ残しました。 消えて困ったことは、いまのところ一度もありません。
2つめは、ホバーしたテーブルに関係する矢印だけを表示することです。 テナントキーを消しても、残った矢印を全部同じ濃さで描けば、テーブルが増えるほどまた絡まってしまうので、通常の矢印は薄く引いておきます。 テーブルにホバーすると、そのテーブルに出入りする矢印と相手のテーブルだけがハイライトされます。 こうすることで、どのテーブルと繋がっているのかが一目でわかります。

3つめは、テーブルにロールのバッジを付けることです。 名前だけにすると、そのテーブルがハブなのか履歴なのかといった役割の手掛かりが消えてしまいます。 そこで、hub(中心)、tx(トランザクション)、child(子)、master(マスタ)、log(履歴)、join(中間)の6種類へ分類し、ボックスへ小さく表示するようにしました。
4つめは、ドメインクラスタの並べ方です。 クラスタを数列のグリッドに配置し、データの流れがおおむね左から右になるように並べます。 FKで強く結ばれたドメイン同士を隣の列に置くと、矢印は短くなり、交錯が減ります。 テーブルの置き場所に迷う問題も、ここで消えました。 新しいテーブルは、属するドメインのクラスタに入れるだけです。
4つの工夫を入れた全体図がこれです。

23テーブル・31本のFKで、この密度に収まります。
スキーマ定義から生成する
図とパネルの二重管理を手で保守できるのか、という疑問は当然あると思います。 少なくとも私には、スキーマが変わるたびに2つを直し続ける根気はありません。
そこで、ビューワのデータはすべてDBスキーマから生成することにしました。 information_schemaやpg_catalogからテーブル、カラム、FKをTSVに書き出し、スクリプトでビューワ用のデータファイルに変換します。 カラム・型・リレーションのいずれも、人は一切書きません。
人が書くのは、スキーマからは機械的に出てこない2つだけです。
- テーブルがどのドメインに属するかの分類
- テーブルの一行説明とロール
といっても、この2つも下書きはAIに任せています。 テーブル名とカラム定義を渡して分類と説明を書かせ、人はレビューだけをします。 設計に関わったテーブルなら、レビューは数分で済みます。
脳のキャッチアップ問題はどうなったか
冒頭で触れた脳のキャッチアップ問題は、覚える対象を絞ることで軽くなりました。 頭に入れるのはドメインの並びと、主要なテーブル名とリレーションだけです。 これなら100テーブルでも頭に入ります。 カラムは必要になったらクリックして確かめれば済みます。
残っている課題
答えの出ていない点も残っています。
- 再生成の自動化:いまはスキーマが変わるたびに手で生成し直している。CIへ組み込まないと、いずれ図と実体が乖離する。
- ドメイン分類の保守:AIの下書きと人のレビューで回しているが、テーブルが増え続けたときにレビューの質を保てるかは未知数である。
- 汎用化:生成スクリプトはプロジェクトごとに書き換える前提の参考実装で、汎用ツールにはなっていない。
- 名前:super ER diagram ← いい名前を募集している。
おわりに
ER図が読めないのは、テーブルが多いからではなく、2つの目的を一枚に詰め込んでいたからでした。 ビューワまで作らなくても、手元のER図からカラムを消してみるだけでも見通しは変わります。
スキーマからテーブル単位のドキュメントとリレーション図を自動生成するアプローチ自体は、tbls1などのツールが先行しています。 この記事の主張はツールではなく、「全体の把握と個別の把握を一枚の図に同居させない」という整理のほうにあります。
ドメインの切り方やロールの分類にはまだ手探りな部分もあるので、フィードバックをもらえるとうれしいです。
Footnotes
-
https://github.com/k1LoW/tbls DBスキーマからドキュメントを自動生成するツール。 ↩