この記事はNTTコムウェア Advent Calendar 2024 7日目の記事です。
こんにちは、NTTコムウェアの濱崎です。
オープンソーステクノロジセンタ なる組織に所属しており、
普段はPostgreSQLに関するノウハウ展開、支援に従事しています。
が、今回はPostgreSQLが主題ではありません。
はじめに
いきなりですが、下の図を見てください。
何か感じましたか?私はイライラしました。
A型の人なら共感してもらえると思います。
誰もが1度は経験したことのある図形配置の煩わしさ。
シンプルな図形や配置なら多少の調整でよいですが、
何か情報を図示するダイアグラムの場合、煩雑になり、微調整で時間が溶けることも...
そこで使えるのがMermaid です。
Mermaidとは
JavaScript ベースのダイアグラム作成およびチャート作成ツールです。
MITライセンスのOSSとして公開されています。
Mermaidで書いたダイアグラムを見てみましょう。
Mermaidテキスト
flowchart LR
A(空腹) -->|食事| B(腹八分)
B --> C{まだ食べる?}
C -->|Yes| D[血糖値スパイク]
C -->|No| E[おいしかった^^]
どうでしょうか?
位置を調整することなく、簡単に整理されたダイアグラムが作成できました。
一番の長所は、ここから変更点がある場合に微調整する必要がない点です。
以下は2行だけ加えて分岐を増やしたものです。
Mermaidテキスト
flowchart LR
A(空腹) -->|食事| B(腹八分)
A(空腹) -->|食事| B'(満腹)
B --> C{まだ食べる?}
C -->|Yes| D[血糖値スパイク]
C -->|No| E[おいしかった^^]
B' --> D[血糖値スパイク]
なお、Mermaid記法を適用する場合はコードブロックを「```mermaid」と書く必要があります。
QiitaはMermaidに対応しています。
上の図も直接Mermaid記法で書いています。
データベースからER図を作成する
MermaidはER図も簡単に作図することができます。
ER図も作成してみましょう。ただし、普通に作成すると面白くないので既存のデータベースから逆輸入してみます。
※ IntelliJ IDEA や DBeaver で簡単にER図を作成できるのはナイショ
ということで、PostgreSQLとMermaidを使って、作成済みのデータベースからER図を作成してみます。
データの用意
PostgreSQL 標準のベンチマークツールである pgbench を使ってデータベースを用意します。
事前に「pgbenchdb」という名前の適当なデータベースを作成しておき、pgbench を実行します。
pgbench コマンドのオプションについては以下を参照ください。
性能測定は行わず、データベースの作成のみを実行します。
$ pgbench -i -I dtGvpf pgbenchdb
pgbench で作成されるテーブルは以下の4つです。
pgbenchで作成されたテーブル
pgbenchdb=# \d+ pgbench_accounts
テーブル"public.pgbench_accounts"
列 | タイプ | 照合順序 | Null 値を許容 | デフォルト | ストレージ | 圧縮 | 統計目標 | 説
----------+---------------+----------+---------------+------------+------------+------+----------+----
--
aid | integer | | not null | | plain | | |
bid | integer | | | | plain | | |
abalance | integer | | | | plain | | |
filler | character(84) | | | | extended | | |
インデックス:
"pgbench_accounts_pkey" PRIMARY KEY, btree (aid)
外部キー制約:
"pgbench_accounts_bid_fkey" FOREIGN KEY (bid) REFERENCES pgbench_branches(bid)
参照元:
TABLE "pgbench_history" CONSTRAINT "pgbench_history_aid_fkey" FOREIGN KEY (aid) REFERENCES pgbench
_accounts(aid)
アクセスメソッド: heap
オプション: fillfactor=100
pgbenchdb=# \d+ pgbench_branches
テーブル"public.pgbench_branches"
列 | タイプ | 照合順序 | Null 値を許容 | デフォルト | ストレージ | 圧縮 | 統計目標 | 説
----------+---------------+----------+---------------+------------+------------+------+----------+----
--
bid | integer | | not null | | plain | | |
bbalance | integer | | | | plain | | |
filler | character(88) | | | | extended | | |
インデックス:
"pgbench_branches_pkey" PRIMARY KEY, btree (bid)
参照元:
TABLE "pgbench_accounts" CONSTRAINT "pgbench_accounts_bid_fkey" FOREIGN KEY (bid) REFERENCES pgben
ch_branches(bid)
TABLE "pgbench_history" CONSTRAINT "pgbench_history_bid_fkey" FOREIGN KEY (bid) REFERENCES pgbench
_branches(bid)
TABLE "pgbench_tellers" CONSTRAINT "pgbench_tellers_bid_fkey" FOREIGN KEY (bid) REFERENCES pgbench
_branches(bid)
アクセスメソッド: heap
オプション: fillfactor=100
pgbenchdb=# \d+ pgbench_history
テーブル"public.pgbench_history"
列 | タイプ | 照合順序 | Null 値を許容 | デフォルト | ストレージ | 圧縮 | 統
計目標 | 説明
--------+-----------------------------+----------+---------------+------------+------------+------+---
-------+------
tid | integer | | | | plain | |
|
bid | integer | | | | plain | |
|
aid | integer | | | | plain | |
|
delta | integer | | | | plain | |
|
mtime | timestamp without time zone | | | | plain | |
|
filler | character(22) | | | | extended | |
|
外部キー制約:
"pgbench_history_aid_fkey" FOREIGN KEY (aid) REFERENCES pgbench_accounts(aid)
"pgbench_history_bid_fkey" FOREIGN KEY (bid) REFERENCES pgbench_branches(bid)
"pgbench_history_tid_fkey" FOREIGN KEY (tid) REFERENCES pgbench_tellers(tid)
アクセスメソッド: heap
pgbenchdb=# \d+ pgbench_tellers
テーブル"public.pgbench_tellers"
列 | タイプ | 照合順序 | Null 値を許容 | デフォルト | ストレージ | 圧縮 | 統計目標 | 説
----------+---------------+----------+---------------+------------+------------+------+----------+----
--
tid | integer | | not null | | plain | | |
bid | integer | | | | plain | | |
tbalance | integer | | | | plain | | |
filler | character(84) | | | | extended | | |
インデックス:
"pgbench_tellers_pkey" PRIMARY KEY, btree (tid)
外部キー制約:
"pgbench_tellers_bid_fkey" FOREIGN KEY (bid) REFERENCES pgbench_branches(bid)
参照元:
TABLE "pgbench_history" CONSTRAINT "pgbench_history_tid_fkey" FOREIGN KEY (tid) REFERENCES pgbench
_tellers(tid)
アクセスメソッド: heap
オプション: fillfactor=100
データベースをSQLファイルに変換する
ER図へ変換する前に、先ほど作成したデータベースをSQLファイルに変換します。
変換のためにpg_dumpを利用します。
pg_dumpはデータベースをバックアップすることのできるコマンドです。他のユーザによるデータベースへのアクセス(読み書き)をブロックしないため、データベースが運用中でもダンプしてスクリプトファイルやアーカイブファイルとして抽出することができます。
データ定義情報のみ取り出したいので、-s (--schema-only) オプションを付ける必要があります。
$ pg_dump -s pgbenchdb > pgbenchdb-schema-only.sql
今回、データベース単位でスクリプトを作成しましたが、各テーブルごとにスクリプトを作成することもできます。
ここまでで、PostgreSQLでの操作は以上です。
SQLからMermaid記法へ変換する
次に、SQLファイルをMermaid記法に変換させる必要があります。
自力で書いてもいいですが、LLMを使って変換させちゃいましょう。
以下のように1文だけ添えて、SQLの中身をコピペしました。
「以下のSQLをmermaid記法に変換してください。~~~」
出力過程は以下を参照ください。
履歴には表示されていませんが、
SQLの中身をバッククォート3つ「```」で囲むとSQLの内容がうまく反映されます。
私の感覚ですが、Mermaid記法への変換精度は高いです。
今回のようなSQLからの変換に限らず、「Mermaid記法」という単語を使用することである程度完成度の高いソースコードが作成されます。
今回、変換前(SQLファイル)と変換後(Mermaidテキスト)を比較してどの程度の精度で変換できたのかは重要ではないので、ほとんど修正せずにそのまま使用します。
作成したMermaidテキストを画像、pdfへ出力する
Mermaidで図示する方法はいくつもあります。
とりあえず試してみたい方は Mermaid Live Editor がオススメです。
今回、VSCodeの拡張機能のみを利用して画像、pdfへ出力します。
使用する拡張機能は以下です。
先ほど作成したMermaidテキストを「.md」拡張子で作成します。
その後、コマンドパレット(ctrl + shift + p)でMarkdown:Open Preview to the Side
を選択して
プレビューを確認できます。
結果がいい感じなら。Markdown側で右クリックを押下し、好きな形式に変換します。
ただし、このままだと図を書き出せず、Markdownのままになってしまいます。
解決策は以下の記事を参考にさせていただきました。
VSCodeの設定からMarkdown-pdf: Mermaid Server
で以下のように設定してください。
(2024/12/03 時点でも、10.5.0以降のバージョンを指定するとうまく変換してくれませんでした。)
これで図を書き出せるようになりました。
最終的に作成したER図はこちら。
Mermaidテキスト
erDiagram
PG_BENCH_ACCOUNTS {
INTEGER aid PK
INTEGER bid FK
INTEGER abalance
CHAR(84) filler
}
PG_BENCH_BRANCHES {
INTEGER bid PK
INTEGER bbalance
CHAR(88) filler
}
PG_BENCH_HISTORY {
INTEGER tid FK
INTEGER bid FK
INTEGER aid FK
INTEGER delta
TIMESTAMP mtime
CHAR(22) filler
}
PG_BENCH_TELLERS {
INTEGER tid PK
INTEGER bid FK
INTEGER tbalance
CHAR(84) filler
}
%% Relationships
PG_BENCH_ACCOUNTS ||--|| PG_BENCH_BRANCHES : "bid"
PG_BENCH_HISTORY ||--|| PG_BENCH_ACCOUNTS : "aid"
PG_BENCH_HISTORY ||--|| PG_BENCH_BRANCHES : "bid"
PG_BENCH_HISTORY ||--|| PG_BENCH_TELLERS : "tid"
PG_BENCH_TELLERS ||--|| PG_BENCH_BRANCHES : "bid"
おわりに
PostgreSQLとMermaid を使って、データベースからER図を出力する方法を紹介しました。
結論、皆さんに伝えたいのが Mermaidはいいぞ ということです。
ただし、CSSでデザインを変更できるのですが、ピクセル単位での位置調整はできないことがたまにキズ。
利用ケースとしては、仕事の成果物として利用するのは難しくても、確認段階での利用に適しているのかなと思います。
記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。