こんにちは、コバヤシです。
弊社では、データベースのドキュメント作成にどのツールを使うべきか試行錯誤してきました。エクセルやGoogleスプレッドシートで作成してみたり、Figmaで描いてみたこともあります。しかし、どれも更新が手間で、更新を忘れてしまい、実態と合わなくなり、そのままでは使えなくなることもしばしばありました。
そんな悩みを抱えていた時、とても便利なツール「tbls」を見つけたので、今回はその紹介と使い方を紹介します。
tblsとは
tblsは、データベーススキーマを自動でドキュメント化するツールです。 MySQLやPostgreSQLなどの主要なRDBMSに対応していて、テーブル構造やリレーション情報を解析してMarkdownやHTML形式で出力できます。手動の更新が不要で、常に最新のドキュメントを維持できるのが利点です。設定ファイルを使えば、特定のテーブルやカラムを除外したり、説明を追加することも可能です。これにより、プロジェクトのスキーマ理解やチームでの情報共有がスムーズになります。
インストール方法
・Goの場合
go install github.com/k1LoW/tbls@latest
・Homebrewの場合
brew install tbls
・dockerを使う場合
docker pull ghcr.io/k1low/tbls:latest
他にもdebやRPMを使ってインストール可能です。
対応するデータベース
対応するデータベースは以下となっています。
- PostgreSQL
- MySQL
- MariaDB
- SQLite
- BigQuery
- Cloud Spanner
- Amazon Redshift
- Microsoft SQL Server
- Amazon DynamoDB
- Snowflake
- MongoDB
- ClickHouse
使い方
tblsは実際にデータベースにアクセスして構造を解析し、ドキュメントを生成します。なので、ドキュメントを作成したいデータベースにアクセスできる状態で、以下のコマンドを実行します。
mysqlの場合 tbls doc mysql://dbuser:dbpass@hostname:3306/dbname
生成されるドキュメント
tblsのdocコマンドを使うと、生成されるのはテーブルのスキーマ情報とER図です。デフォルトでは、schemaディレクトリにMarkdown形式のドキュメントと、SVG形式のER図が出力されます。
出力されるディレクトリ構造の例は以下のようになります。
├── schema │ ├── README.md │ ├── users.md │ ├── orders.md │ ├── xxxxxx1.svg │ └── xxxxxx2.svg
概要を記載したREADME.mdファイルも自動的に生成されるため、これをGitHubやWikiにアップロードすれば、仕様書を簡単に共有できます。
tbls docコマンドのオプション
tbls docコマンドには様々なオプションがあります。
オプション | 説明 |
---|---|
-j, --adjust-table | カラム幅を調整してテーブルを表示 |
-b, --base-url string | リンク用のベース URL を指定。 |
-c, --config string | 設定ファイルのパスを指定。 |
-t, --er-format string | ER図の出力形式を指定(png, svg, jpg, mermaid)。 |
-f, --force | ドキュメントを強制的に上書き。 |
--rm-dist | 出力ディレクトリのファイルを削除してから生成。 |
--sort | テーブルリストとカラムをソート。 |
--when string | 実行条件を指定。(詳細はわからず) |
--without-er | ER図を生成しない |
その他のコマンド
tbls diff
tbls diff コマンドは、データベースの現在のスキーマと、以前に生成されたドキュメントを比較し、差分を表示します。スキーマの変更点を簡単に確認でき、CIにも活用できます。
tbls lint
tbls lint コマンドは、データベーススキーマのドキュメントが正しく記述されているかを検証します。テーブルやカラムに説明が不足している箇所を指摘し、ドキュメントの品質を保つために役立ちます。これらの検証ルールは後述するtbls.ymlファイルで管理できます。
tbls coverage
tbls coverage コマンドは、データベーススキーマのドキュメントカバレッジを測定します。テーブルやカラムに対する説明やコメントがどれだけ記述されているかを可視化します。これにより、ドキュメントの品質を向上させることができます。
tbls.ymlファイル
tbls.yml ファイルは、tblsの設定ファイルです。データベースの接続情報や、ドキュメント生成時の出力設定、Lintのルールなどをの設定を定義します。
設定できる項目は以下となります。
dsn
データベースの接続設定を指定します。
dsn: mysql://dbuser:dbpass@hostname:3306/dbname
name
データベース名を指定します。
name: 書籍管理DB
docPath
出力先のパスを指定します。
docPath: doc/schema
labels
データベースにラベルを設定します。
labels: - books
format
ドキュメントの出力を指定します。
format: # Markdown 形式のテーブルの列幅を調整 デフォルトは false adjust: true # テーブルリストとカラムの順序をソート デフォルトは false sort: false # テーブルの行に連番を表示 デフォルトは false number: false # インデックスページの各テーブルのコメントを省略表示 デフォルトは false showOnlyFirstParagraph: true # 値がないテーブルのカラムを非表示 デフォルトは false カラム配列として指定可能 hideColumnsWithoutValues: true
er
ER図の出力を指定します。
er: # ER図の生成をしない デフォルトは false skip: false # ER図の画像形式 (`png`, `jpg`, `svg`, `mermaid`) デフォルトは `svg` format: svg # テーブルやカラムのコメントを ER図に追加 デフォルトは false comment: true # ER図からリレーション定義を非表示にする デフォルトは false hideDef: true # ER図にカラム設定を表示する(未設定の場合、すべてのカラムを表示) showColumnTypes: # 関連カラムを表示 related: true # 主キーのカラムを表示 primary: true # ER図のテーブル間の距離 デフォルトは 1 distance: 2 # ER図のフォント デフォルトは ""(システムデフォルト) font: M+
lint
tbls lint コマンドでチェックする内容を指定します。
lint: # テーブルコメントを必要とする requireTableComment: enabled: true # 全てコメントがあるか、ないか allOrNothing: false # カラムコメントを必要とする requireColumnComment: enabled: true # 全てコメントがある、もしくはない、のどちらか allOrNothing: true # チェックから除外するカラム exclude: - id - created_at - updated_at # 除外するテーブル excludeTables: - logs - comment_stars # インデックスのコメントを必要とする requireIndexComment: enabled: true # 全てコメントがある、もしくはない、のどちらか allOrNothing: false # 警告から除外するインデックス exclude: - user_id_idx # 除外するテーブル excludeTables: - logs - comment_stars # 制約コメントが必要 requireConstraintComment: enabled: true # 全てコメントがある、もしくはない、のどちらか allOrNothing: false # 除外する制約 exclude: - unique_user_name # 除外するテーブル excludeTables: - logs - comment_stars # トリガーコメントを必要とする requireTriggerComment: enabled: true # 全てコメントがある、もしくはない、のどちらか allOrNothing: false # 除外するトリガー exclude: - update_count # 除外するテーブル excludeTables: - logs - comment_stars # テーブルラベルを必要とする requireTableLabels: enabled: true # 全てラベルがある、もしくはない、のどちらか allOrNothing: false # 除外するテーブル exclude: - logs # リレーションのないテーブルを検出 unrelatedTable: enabled: true # 全て関連している、もしくはない、のどちらか allOrNothing: true # 除外するテーブル exclude: - logs # カラム数をチェック columnCount: enabled: true max: 10 # 除外するテーブル exclude: - user_options # 必須カラム requireColumns: enabled: true columns: - name: created - name: updated exclude: - logs - CamelizeTable # 重複リレーションをチェック duplicateRelations: enabled: true # 外部キーにインデックスがあるかをチェック requireForeignKeyIndex: enabled: true exclude: - comments.user_id # BigQuery スタイルのラベルをチェック labelStyleBigQuery: enabled: true exclude: - schema_migrations # テーブルが少なくとも1つのViewpointに含まれているかをチェック requireViewpoints: enabled: true exclude: - schema_migrations
include
ドキュメント生成するテーブルを指定します。*
を使ってワイルドカードでテーブルの指定もできます。
include: - some_prefix_*
exclude
ドキュメントの生成から除外するテーブルを指定します。
exclude: - some_prefix_logs - CamelizeTable
lintExclude
Lintチェックから除外するテーブルを指定します。
lintExclude: - CamelizeTable
comments
コメントを指定します。通常はスキーマ情報からコメントを取得しますが、別途コメント指定したい場合には記述します。
comments: - table: users # テーブルコメント tableComment: Users table # カラムコメント columnComments: email: Email address as login id. ex. user@example.com - table: posts # インデックスコメント indexComments: posts_user_id_idx: user.id index # 制約コメント constraintComments: posts_id_pk: PRIMARY KEY # トリガーコメント triggerComments: update_posts_updated: Update updated when posts update
relations
リレーションを指定します。通常はスキーマ情報からリレーションを取得しますが、別途リレーションを指定したい場合には記述します。
relations: - table: logs columns: - user_id # 親テーブル parentTable: users # 親カラム parentColumns: - id # リレーション定義の表示 指定しない場合は `Additional Relation` def: logs->users
detectVirtualRelations
リレーションを自動検出するかどうかを設定します。strategyで指定した検出方法に基づき、テーブルやカラム名からリレーションを推測して生成します。
detectVirtualRelations: enabled: true strategy: default
指定出来るstrategyと検出方法は以下です。
strategy | リレーション元 | リレーション先 |
---|---|---|
default | some_table.user_id | users.id |
singularTableName | some_table.user_id | user.id |
identical | some_table.user_id | users.user_id |
identicalSingularTableName | ome_table.user_id | user.user_id |
dict
ドキュメント生成時に使用される単語を、指定した文字に置き換えることができます。 以下を指定するとドキュメントが日本語化されます。
dict: Tables: テーブル一覧 Description: 概要 Columns: カラム一覧 Indexes: INDEX一覧 Constraints: 制約一覧 Triggers: トリガー Relations: ER図 Name: 名前 Comment: コメント Type: タイプ Default: デフォルト値 Children: 子テーブル Parents: 親テーブル Definition: 定義 Table Definition: テーブル定義
Viewpoints
Viewpointsは、データベース内のテーブルを論理的にまとめる機能です。これにより、関連するテーブルをまとめ、特定の視点からスキーマを整理できます。大規模なデータベースで、特定のテーブル群に焦点を当てたい場合に非常に役立ちます。
さらに、Viewpointsの下にはサブグループを作成することも可能です。これにより、階層的にテーブルをグループ化し、より詳細な分類や整理が可能になります。例えば、ユーザー管理に関連するテーブルを一つのViewpointにまとめ、その中でさらに「ユーザー情報」「認証情報」などのサブグループを作成して管理することができます。
viewpoints: - name: comments on post desc: Users can comment on each post multiple times and put a star on each comment. tables: - users - posts - comments - comment_stars - post_comments - post_comment_stars groups: - name: Comments desc: Tables about comments tables: - posts - comments - post_comments - name: Stars desc: Tables about stars tables: - comment_stars - post_comment_stars
エクセルで出力
エクセルファイルでの出力もできます。
ただER図は出力されませんでした。
tbls out -t xlsx -o schema.xlsx
CI連携
GitHub ActionsなどのCIツールに組み込むことで、Lintチェックやドキュメント生成を自動化できます。これにより、常に最新のデータベース仕様書を維持し、実態に沿ったドキュメント管理が可能になります。
GitHub Actionsに組み込むならこんな感じです。
jobs: run-tbls: runs-on: ubuntu-latest services: mysql: image: mariadb:10.4 env: MYSQL_ROOT_PASSWORD: ${{ secrets.DB_PASSWORD }} MYSQL_DATABASE: ${{ secrets.DB_DATABASE }} ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=10s --health-retries=3 env: DB_CONNECTION: ${{ secrets.DB_CONNECTION }} DB_HOST: ${{ secrets.DB_HOST }} DB_PORT: ${{ secrets.DB_PORT }} DB_DATABASE: ${{ secrets.DB_DATABASE }} DB_USERNAME: ${{ secrets.DB_USERNAME }} DB_PASSWORD: ${{ secrets.DB_PASSWORD }} DB_CHARSET: ${{ secrets.DB_CHARSET }} DB_COLLATION: ${{ secrets.DB_COLLATION }} DB_DSN: ${{ secrets.DB_CONNECTION }}://${{ secrets.DB_USERNAME }}:${{ secrets.DB_PASSWORD }}@${{ secrets.DB_HOST }}:${{ secrets.DB_PORT }}/${{ secrets.DB_DATABASE }} steps: - name: Checkout code uses: actions/checkout@v4.1.0 with: fetch-depth: 0 ref: ${{ github.head_ref }} - name: Set up Git identity run: | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - name: Set up PHP uses: shivammathur/setup-php@v2 with: php-version: '8.2' extensions: mbstring, xml, ctype, iconv, mysql, pdo_mysql tools: composer - name: Get composer cache directory id: composer-cache run: | echo "COMPOSER_CACHE_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV working-directory: laravel - name: Cache composer dependencies uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: | ${{ runner.os }}-composer- - name: Composer install run: composer install --no-progress --prefer-dist --optimize-autoloader working-directory: laravel - name: Run migrations run: php artisan migrate --force working-directory: laravel - name: Install tbls uses: k1low/setup-tbls@v1 - name: Run tbls lint run: tbls lint $DB_DSN - name: Run tbls diff id: diff run: tbls diff $DB_DSN continue-on-error: true - name: Generate New Documentation if: steps.diff.outcome == 'failure' run: tbls doc $DB_DSN --rm-dist - name: Check for file changes run: | if [ -n "$(git status --porcelain)" ]; then echo "git_changes=true" >> $GITHUB_ENV else echo "git_changes=false" >> $GITHUB_ENV fi - name: Commit and Push changes if: env.git_changes == 'true' run: | git add . git commit -m "tbls create schema" git push origin ${GITHUB_HEAD_REF}
tbls lintを実行してドキュメントのLintチェックを行うのと、 tbls diffを実行して、差分があった場合のみドキュメントの再生成を行いコミットを実行します。
tblsでは、テーブル定義としてSQLの CREATE文が生成されますが、AUTO_INCREMENT が設定されたテーブルにローカルでデータがある場合、AUTO_INCREMENT の値が出力されます。一方で、GitHub ActionsなどのCI環境で実行した際、テーブルが空の場合は AUTO_INCREMENT の値が出力されません。
その結果、スキーマに実際の変更が無くても差分が発生し、不要なコミットが行われることがあります。これを防ぐためには、GitHub Actionsの実行時にデータを挿入しておくことで(例えばテストの流れでデータを投入)、AUTO_INCREMENT の差分を抑えられます。
まとめ
tblsを使用することで、データベース仕様書の作成や更新が自動化され、手動での管理の手間を大幅に削減できます。さらに、GitHub ActionsなどのCIツールに組み込むことで、Lintチェックやドキュメント生成を自動化できます。これにより、常に最新のデータベーススキーマをドキュメントに反映させ、スキーマの変更を効率的に管理できるようになります。 論理カラム名の指定や、コメント以外に説明を追加できる機能など、さらなる要望もありますが、現状の機能でも十分対応できるので良しとします。今後はtblsを使って効率的なデータベース管理を目指していきたいと思います。