🦍

DBスキーマはtblsのViewpointsで整理しよう

2023/12/05に公開

この記事は MICIN Advent Calendar 2023 の 5日目の記事です。

https://adventar.org/calendars/9595

前回は竹内さんの、Socket.ioコンテナオーケストレーションハンズオン でした。

tblsはいいぞ🦍

筆者はtblsの大ファンであり、特にViewpoints機能が他のツールとは一線を画していると思っています。今回はその良さをお伝えできればと思います。

TL;DR

  1. tblsは実際のスキーマからDBのドキュメントを生成するツール
  2. ER図が巨大化しても、tblsのViewpointごとに分割することでDBの全体像が理解可能になる
  3. Viewpointの粒度に困ったら一旦トランザクションと集計の単位に設定する
  4. 個別のテーブルとViewpointは相互に参照できる
  5. CIに組み込むことでドキュメンテーション忘れを防げる

なんのためにDBのドキュメンテーションを行うか

DBのドキュメンテーションはそれなりにコストがかかるため、おざなりにされることも少なくありません。
しかし、下記のようなケースを考えるとドキュメンテーションは必須であると言えるでしょう。

  • 再来月の全て忘れた自分が思い出すため
  • 開発チームに新規参加したメンバーがキャッチアップするため
  • 運用チームがSQLでDBにアクセスしてトラブルシュートするため
  • 解析チーム、データ基盤チームが既存のDBの内容を理解するため

よくあるDBドキュメンテーションの課題

DBのドキュメンテーションは下記のような課題を抱えていることが多いです。

  • メンテナンスされない
  • 存在が知られていない
  • ER図が大きすぎて読めない
  • そもそも存在しない

tblsというツールを使うと上記のような問題が軽減され、簡単に有用なドキュメントをメンテナンスできます。

tblsを使う

tblsとは

https://github.com/k1LoW/tbls
https://speakerdeck.com/k1low/phpconfuk-2023?slide=7

  • 既存のDBスキーマからER図、テーブル一覧、テーブル詳細などのドキュメントを生成
  • Markdown形式なのでGitHubのリポジトリから参照でき、ホスティングが不要
  • カラムコメント、テーブルコメントの有無などを検証
  • CIへの組み込みが容易
  • Viewpoints機能が非常に強力

tblsによって生成されるドキュメント

tbls docコマンドを実行すると、DBスキーマからドキュメントが生成されます。
実際に生成されたドキュメントは下記のような形で見えます。
(※今回のスキーマは架空の通販サービスのDBを想定しています。筆者は通販サービスの設計をしたことがないため、ドキュメント内の内容についてはご容赦ください。)

リポジトリはこちらです。
https://github.com/majimaccho/prisma-tbls

トップのドキュメント

最も上位の全体観を表すドキュメントがREADME.mdという名前で生成されます。
トップのドキュメントにはViewpointsとテーブル一覧、ER図が含まれます。
下では説明のために分割していますが、Viewpoints〜ER図まで1つのREADME.mdファイルです。
ひとつのファイルとしてみたい方はぜひ上のリポジトリのリンクからご確認ください。

Viewpoints

viewpoints

Viewpointsというのはtbls独自の概念で、DBのスキーマを任意のまとまりに分割できます。
DDLでの設定ではなく、tblsの設定ファイルのYAMLに記述します。
このViewpoints機能が非常に強力で、DBのスキーマを理解するのに役立ちます。
この機能は他のツールにはない機能で、tblsを使う大きなメリットの1つです。

Viewpointsを設定している場合、生成されたREADME.mdの最上部にViewpointの一覧が来ます。
Viewpointsには任意のテーブルのまとまりを定義でき、tblsの設定ファイルのYAMLに記述することで自由に追加できます。
Viewpointの一覧を見ることで、そのDBに格納されているデータの概要を理解するのに役立ちます。

テーブル一覧

tables

ER図

ER図のフォーマットはsvg, png, mermaidなどから選べます。今回はmermaid形式にしています。

erd

トップのドキュメントのER図はテーブル数が非常に大きくなりやすく、プロジェクトの早期にも理解が難しくなります。この問題はViewpoints機能が解消してくれます。

個別のViewpointのドキュメント

トップのドキュメントにある、Viewpoint一覧のそれぞれの名前は個別のViewpointのドキュメントへのリンクになっています。
個別のViewpointのドキュメントには下記の内容が含まれています。

  • 概要
  • 内包するテーブルの一覧
  • 内包するテーブルのER図

テーブル一覧のコメントの列には実際にDBのスキーマ上にDDLで定義されているテーブルコメントが入ります。

viewpoint1
viewpoint2

DB全体のテーブル数が膨大になり、テーブル一覧やER図自体を読み解くことが難しくなっても、Viewpointsを糸口に全体像を理解し、個別のテーブルに意識を向けることが自然とできるようになります。

個別のテーブルのドキュメント

各ドキュメントのテーブル一覧の各テーブル名は個別のテーブルのドキュメントのリンクになっています。
個別テーブルのドキュメントは下記の内容を含んでいます。

  • 概要(テーブルコメント)
  • カラム一覧
  • Viewpoints
  • 制約一覧
  • インデックス一覧
  • ER図

また、親テーブルや子テーブル、Indexやその他の制約が確認でき、各カラムにはカラムコメントが対応して表示されています。

table1
table2
table3

ここで強調したいのは個別のテーブルからそのテーブルを含むViewpointを一覧で見られる点です。[1]
複数文脈で利用されるテーブルがどのように参照されるかを一箇所見るだけで把握できるようになります。
これは作成や参照のユースケースを知ったり、Viewpoints同士の関係性を理解するのに役立ちます。

Viewpointsの設定の仕方

Viewpointsはtblsの設定ファイルのYAML(.tbls.yml)に下記のような形で記述します。

キー 説明
name Viewpointの名前
desc Viewpointの説明
tables Viewpointに含まれるテーブルの一覧
# .tbls.yml
# 他の設定は省略
viewpoints:
  - 
    name: 書籍の購入
    desc: >
      書籍を購入する際に関連するテーブルのまとまり。
      顧客が購入できるためには、配送先が設定される必要がある。
      配送時に参照される製品コードはproductsテーブルから取得される。
    tables:
      - books
      - products
      - customers
      - shipping_addresses
      - orders
      - order_items
  - # 省略

上記の設定以外にもgroupを設定したり、ラベルを設定したりできます。

Viewpoints機能を(筆者は)どのように使うのか

Viewpointsを設定する単位

Viewpointsを設定する単位は組織やプロダクトの規模や構成によって異なります。
個人的にはViewpointはトランザクションと集計の単位で設定すると悩まずに設定できると考えています。
トランザクションと集計の範囲ごとにViewpointがあることで、作成時の整合性の担保しなければいけない範囲を明示できます。
テーブルごとのViewpoint一覧を見るときにもある程度、細かく、かつ意味のある単位になっている方が、変更時の影響範囲を特定するときなどに有用です。

プロジェクトの規模が大きいときにはこの粒度では小さすぎることもあります。
その場合、全体観がわかりやすいようにするためにより大きい粒度でViewpointsを設定することを検討してください。

Viewpointsを通してDBを"みる"

Viewpointsは以下の内容のために役立ちます。

  • 全体像の把握
  • テーブルの意味的なまとまりの理解
  • 個別のテーブルの参照され方の理解

全体像の把握

巨大化したプロジェクトにおいて、テーブル一覧とER図をそのまま理解することは困難です。
テーブル数が3桁になるとノートPCのモニターでER図を見るとテーブル名を見ることも難しいでしょう。
その代わりに、Viewpointsの一覧が全体像の理解を進めます。テーブルよりも大きな粒度でデータを認識できるため、認知負荷が低いです。個別のテーブルを見に行く前の入り口の役目もはたします。

テーブルの意味的なまとまりの理解

Viewpointsはデータのまとまりを表現できます。
個別のテーブルとその親子テーブルが見えるというのは他のツールでもありますが、任意のまとまりを設定できることでドキュメンテーションの柔軟性が高まります。

個別のテーブルの参照され方の理解

また、個別のテーブルがどのViewpointから参照されているかがわかることも読み手にとって有益です。これにより、個別のテーブルに関連する部分を変更する際のDBレベルでの影響範囲を確認できます。

テーブルコメントに何を書くか

tblsを利用している場合は特に下記のような内容をテーブルコメントに設定すると有用です。

  • テーブル名の補足(和訳/どの画面/機能の名前と対応するなど)
  • 親テーブルとの関係
  • テーブル名からは推測できない周辺の文脈

これらがコメントとして設定されていると、上述の各ドキュメントで参照される際に、内容を理解しやすくなります。
特にテーブルコメントはtblsのドキュメント生成においては重要な位置を占めます。
トップのドキュメントやViewpointsのドキュメントのテーブル一覧でも表示されますし、個別のテーブルのドキュメントの概要の部分に当たります。

カラムコメントに何を書くか

筆者がカラムコメントを設定する際には、下記のような内容を設定することが多いです。こちらは一般的な内容かと思います。

  • カラム名の説明(和訳/どのフォーム・表示の項目と対応するかなど)
  • 入る値の期待値、ルール
  • カラム名からは推測できない周辺の文脈

リント機能

tblsはドキュメントの生成だけでなく、tbls lint コマンドを使うことでDBスキーマに対してリントを行うことができます。
こちらで、筆者のおすすめのリントルールを3つご紹介します。
これらのリントルールを活用することで、ドキュメントのメンテナンスが忘れられてしまうことを防ぎ、tblsから生成されるドキュメントをより充実させることができます。

requireColumnComment(カラムコメントの必須化)

カラムコメントが設定されていないカラムがあるとリントエラーになります。
どのカラムに設定されていないかを出力してくれます。
オプションでid, created_atなど任意の名前のカラムを対象外にできます。

requireTableComment (テーブルコメント必須化)

requireColumnCommentのテーブルコメント版です。
テーブルコメントが設定されていないテーブルがあるとリントエラーになります。

requireViewpoints (Viewpoints必須化) [2]

こちらはスキーマのリントではありませんが、Viewpointの設定を検証してくれます。
全てのテーブルがそれぞれ1つ以上のViewpointに属していなければリントエラーになります。

これらの他にも、カラム数の制限や、制約のコメントの必須化などいくつかリントルールがあるので詳しくは公式READMEをご確認ください。

https://github.com/k1LoW/tbls?tab=readme-ov-file#lint

CIへの組み込み

tblsはCIに組み込むことでより有効に活用できます。
上記のリント機能はもちろん、tbls diffコマンドで既存のドキュメントと、実際のDBのスキーマから生成されるべきドキュメントの差分を検出してくれるため、コミット忘れを防ぐことができます。

GitHub Actionsを利用する場合、下記のようにするとリントと差分の検出が行えます。

# .github/workflows/doc.yml
jobs:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout .tbls.yml
        uses: actions/checkout@v3
      # 
      # SET UP YOUR DATABASE AND RUN ALL MIGRATION
      # 
      -
        uses: k1low/setup-tbls@v1
      -
        name: check diff of tbls documents
        run: tbls diff # ドキュメントのコミット忘れの検出
      - 
        name: lint your schema
        run: tbls lint # リントの実行

最後に

tblsのViewpointsは競合のドキュメント生成ツールと比較しても、一線を画す機能です。導入〜CI構築までもかなりお手軽にできるので読者の皆様も試していただけると1人のtblsのファンとして嬉しいです。


MICINではメンバーを大募集しています。
「とりあえず話を聞いてみたい」でも大歓迎ですので、お気軽にご応募ください!

https://recruit.micin.jp/

脚注
  1. この機能は筆者がViewpoints機能のことを好きすぎてコミットした機能です。(その1)
    https://github.com/k1LoW/tbls/pull/532 ↩︎

  2. この機能は筆者がViewpoints機能のことを好きすぎてコミットした機能です。(その2)
    https://github.com/k1LoW/tbls/pull/517 ↩︎

GitHubで編集を提案
株式会社MICIN

Discussion