データベース設計規約
はじめに
データベース設計はソフトウェアシステムの中核基盤であり、その標準化はシステムの性能、安定性、保守性に直接影響します。各種製品のデータ構造とシステムアーキテクチャの一貫性を保証するため、千桐科技は本「データベース設計規約」を策定しました。
本規約は、長期にわたるプロジェクト実践で得た経験を集約したものであり、qKnow ナレッジプラットフォーム、qData データ基盤、qThing IoT プラットフォーム、qModel モデル管理プラットフォーム など、千桐科技の各製品が統一して従う設計標準になっています。標準化されたデータベース設計により、チームは複数プロジェクトの並行デベロップメントにおいて構造とスタイルを統一し、システム性能とデベロップメント効率を高め、製品の高品質と拡張性を確保できます。
1. モジュール設計
1. モジュール分割規約
モジュール分割はデータベース設計の基礎工程です。業務ロジックが明確、構造が合理的、保守と拡張が容易であることを原則とし、デベロップメント、反復、後続運用における継続性を保証します。
業務駆動: モジュール分割は実際の業務要件に基づきます。各モジュールは明確な機能または業務フローに対応し、人為的な分割や任意の積み上げを避けます。
例:- ユーザー管理モジュール(User Management Module)は、ユーザー登録、ログイン、ロール割り当てなどを担当します。
- プロジェクト管理モジュール(Project Management Module)は、プロジェクト情報保守、タスク割り当て、進捗追跡を担当します。
- レポートモジュール(Report Module)は、データ統計と可視化閲覧を担当します。
高凝集・低結合: モジュール間の結合はできるだけ低くし、モジュール内部機能の高い凝集性を確保します。たとえば、ユーザー管理モジュール(um)はプロジェクト管理モジュール(pm)のテーブル構造へ直接依存せず、インターフェースまたはサービス層を通じて連携します。
説明: あるモジュールが別モジュールのインターフェースを頻繁に呼び出す場合、分割に問題がある可能性があり、責任境界を再確認する必要があります。階層設計: モジュール分割は業務ロジックと機能階層に基づいて設計できます。通常は次を含みます。
- 基盤層: DB連携、共通ユーティリティなど。
- ロジック層: 業務ルール計算、状態機械処理など。
- アプリケーション層: ユーザーインターフェース、APIサービス、フロントエンド連携ロジックなど。
階層構造は、システム分離、テスト分離、分散デプロイに役立ちます。
均衡性: モジュール分割はできるだけ均衡させ、一部モジュールが過大になること、たとえば数百テーブルを含むことを避けます。後続の保守と拡張へ影響するためです。単一モジュールが管理するテーブル数は30以下を推奨し、超過する場合はさらに分割を検討します。
柔軟性と拡張性: モジュール設計では将来の拡張や変更を考慮し、過度な結合を避け、柔軟性と拡張性を保ちます。たとえば、ユーザーモジュールで将来マルチテナント対応が必要になる可能性がある場合、設計初期に
tenant_idフィールドを予約するか、独立 schema 方式を採用します。
2. モジュール命名規約
良いモジュール命名は、データベースの可読性と保守性の基礎です。モジュール命名は統簡潔、有意義の原則に従い、チームメンバーが一目で理解できるようにします。
簡潔で有意義: モジュール名は簡潔で、モジュールの機能を明確に表す必要があります。長すぎる名前や抽象的すぎる名前は避けます。
例:- ユーザー管理モジュール →
userまたはum - プロジェクト管理モジュール →
projectまたはpm
- ユーザー管理モジュール →
略称を使用: モジュール名はテーブル名のプレフィックスになるため、適切な略称に簡略化し、合理的な長さ、通常2-4文字以内にします。よくある例:
モジュール名 略称 テーブル名例 ユーザー管理モジュール um um_user プロジェクト管理モジュール pm pm_project システム設定モジュール sc sc_config 冗長性を避ける: 名前に「system」「management」などの冗長語を使わず、モジュールの中核機能を反映します。
非推奨:user_manage_system
推奨:um_user統一命名ルール: すべてのプロジェクトで統一された命名規約を採用し、チームやデベロップメント者ごとの命名差による保守性低下を避けます。プロジェクト開始時に、アーキテクチャチームがモジュール略称対応表を統一して公開することを推奨します。
2. データベース命名規約
1. 環境別命名
デベロップメント、テスト、本番環境のデータ分離とデプロイ安全性を保証するため、データベース名は環境を厳密に区別する必要があります。
デベロップメントDB:
[project_code]_dev
例:qData_dev、qKnow_devテストDB:
[project_code]_test
例:qData_test、qModel_test本番DB:
[project_code]_prod
例:qKnow_prod、qThing_prod
⚠️ 注意: 本番環境で
_devまたは_testサフィックスのDBを直接使用することは禁止します。
2. プロジェクトコード命名
- プロジェクトコードは短く、通常2-10文字、かつ一意で業務識別性があり、異なるプロジェクトのDBを管理および区別しやすいものにします。
- 例:
qData(千桐データ基盤)、qKnow(千桐ナレッジプラットフォーム)、qAuth(統一ID認証プラットフォーム)
- 例:
3. 統一命名ルール
- すべての環境でDB命名形式を統一し、運用担当者が環境種別を素早く識別できるようにします。
- DB作るスクリプトや CI/CD 設定ファイルで命名規約を強制検証することを推奨します。
3. テーブル設計
1. テーブル命名規約
- 小文字とアンダースコア: すべてのテーブル名は小文字を使い、単語間をアンダースコアで区切ります。
✅ 正しい例:user_info、order_details、product_category
❌ 誤った例:UserInfo、ORDERDETAILS、user-info
💡 Oracle 環境で大文字を好むなど、顧客に特別な要件がある場合は、PDManer などのモデリングツールで DDL エクスポート時に大文字小文字を統一変換できます。ただし論理設計段階では小文字を基準とします。
簡潔かつ正確: テーブル名は短く、保存するデータエンティティを正確に反映する必要があります。
例:um_user: ユーザー管理モジュール内のユーザー主テーブルpm_project: プロジェクト管理モジュール内のプロジェクト主テーブル
業務用語の曖昧化を避ける: 「data_table」「record_table」「info_table」などの曖昧な語は使用しないでください。
user_data_tableではなくuserのように、エンティティ自体へ集中します。特殊文字と数字を避ける: テーブル名に空白、日本語/中国語文字、
-、#、@などの特殊文字を含めてはいけません。また純数字で始まったり終わったりしないようにします。プレフィックスルール: すべての業務テーブルは、所属モジュールの略称をプレフィックスとして使用します。
例:um_user_role_rel(ユーザー-ロール関連テーブル)om_order_history(注文履歴テーブル)sm_system_config(システム設定テーブル)
2. 特殊種別テーブルの命名識別子
DB可読性を高めるため、特定用途のテーブルには統一サフィックス識別子を使用します。
| テーブル種別 | 命名サフィックス | 例 | 説明 |
|---|---|---|---|
| 関連テーブル | _rel | um_user_role_rel | 多対多関連テーブル |
| ログテーブル | _log | sm_operation_log | 操作ログ、エラーログなど |
| 履歴テーブル | _history | om_order_history | データ変更履歴を記録 |
| 設定テーブル | _config | sm_app_config | システムまたはアプリケーションレベルの設定パラメーターを保存 |
📌 推奨: 履歴テーブルとログテーブルは定期的にアーカイブし、主DBの肥大化を避けます。
4. フィールド設計
1. フィールド論理名命名規約(技術命名)
短く明確: フィールド名は業務上の意味を表す必要があります。例:
user_id、order_amount。uid、amtなどの過度な略称は避けます。小文字とアンダースコア: フィールド名は小文字 + アンダースコア形式に統一します。
✅ 例:create_time、request_ip、del_flag予約語を避ける:
order、group、desc、userなどの SQL 予約語をフィールド名として使用することは禁止します。どうしても使用する場合はバッククォートが必要ですが、推奨しません。統一命名ルール: 同じ意味のフィールドは異なるテーブルでも同じ名前にします。
例: すべてのテーブルの「作る者」フィールドはcreate_byとし、creatorやcreated_by_userにはしません。
2. フィールド名命名規約(業務命名 / コメント閲覧用)
注: ここでの「フィールド名」は、PDManer、PowerDesigner などのDBモデリングツールで閲覧する論理フィールド名を指し、物理列名ではありません。
業務向け命名: データモデル文書やER図では、業務担当者が理解できる説明をフィールドに付けます。
例:- 物理列名:
user_id→ 論理名:ユーザーID - 物理列名:
create_time→ 論理名:作る日時
- 物理列名:
簡潔明瞭: 技術用語の詰め込みを避け、「ユーザー一意識別子」は「ユーザーID」に簡略化します。
曖昧さを避ける: 「時刻」は「作る日時」または「アップデート日時」のように明確にし、「時刻」だけにしないでください。
3. フィールドコメント規約
高品質なフィールドコメントは、DBの自己文書化の鍵です。
簡潔明瞭: コメントは一文でフィールド用途を説明します。
例:user_statusのコメントは「ユーザー状態: 0-無効、1-有効」業務駆動: コメントは技術実装ではなく、ユーザーまたは業務視点から記述します。
✅ 良いコメント: 「マーケティングSMSを受信するか(0-いいえ、1-はい)」
❌ 悪いコメント: 「SMS購読用のBooleanフラグ」コメント内容には次を含めます:
- フィールドの業務意味
- 列挙値説明(ある場合)
- NULL を許可するか
- 主キー/外部キーか
- 既定値(ある場合)
統一スタイル: 次のテンプレートを推奨します。
「[業務意味]。値: [列挙説明]。[その他制約]」
例:
「注文支払状態。値: 0-未払い、1-支払済み、2-返金済み。非NULL。」SQL例:
CREATE TABLE um_user (
id BIGINT PRIMARY KEY COMMENT '主キーID。非NULL、ユーザーレコードを一意に識別。',
username VARCHAR(50) NOT NULL COMMENT 'ユーザー名。一意かつ非NULL。',
password VARCHAR(100) NOT NULL COMMENT 'ログインパスワード。暗号化保存、非NULL。',
status TINYINT DEFAULT 1 COMMENT 'ユーザー状態。値: 0=無効、1=有効。非NULL、既定値1。',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'レコード作る日時。既定値は現在時刻。',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'レコード最終アップデート日時。自動アップデート。'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ユーザー情報テーブル。システムユーザーの基本情報を保存。';4. フィールドデータ型設定規約
データ型を適切に選択:
業務場面 推奨型 例 ユーザーID、注文ID BIGINT 自動採番主キーまたはSnowflake ID ユーザー名、メール VARCHAR(50~255) 実際の長さに基づき見積もる パスワード VARCHAR(100) 暗号化後の文字列を保存 金額 DECIMAL(18,2) FLOAT/DOUBLE は避ける 作る日時 DATETIME 秒単位まで正確 取り除き済みか TINYINT(1) 0-いいえ、1-はい 長文、説明など TEXT 64KB 超過は非推奨 プリセット型設定: DBモデリングツールで「標準主キー」「標準タイムスタンプ」などのよく使うフィールドテンプレートを事前定義し、設計時に再利用できるようにすることを推奨します。
拡張性を考慮: たとえば電話番号は現在11桁でも、将来国際番号に対応する可能性があるため、
CHAR(11)ではなくVARCHAR(20)を推奨します。過剰設計を避ける: 「将来使うかもしれない」場面のために過大なフィールドを予約しないでください。たとえばユーザー閲覧名は通常30文字を超えないため、
VARCHAR(255)は不要です。
5. フィールド順序の原則
合理的なフィールド順序は、可読性とクエリ効率の向上に役立ちます。
1. 通常フィールド順序(推奨順)
- 主キーフィールド(例:
id) - 外部キーフィールド(例:
user_id,project_id) - 中核業務フィールド(例:
username,order_no,amount) - 状態/分類フィールド(例:
status,type,gender) - メタデータフィールド(例:
create_by,create_time,update_time,del_flag)
例:
um_userテーブルのフィールド順
id,
tenant_id, -- マルチテナント場面
username,
email,
phone,
status, -- 0-無効 1-有効
gender, -- 性別: 0-不明 1-男性 2-女性
create_by,
create_time,
update_time,
del_flag2. 種別フィールド順序
- 分類フィールドは前へ:
gender、user_type、order_sourceなどは WHERE 条件での絞り込みを容易にするため前方に設置します。 - 列挙フィールドを優先: 状態など高頻度で使う列挙フィールドは、業務フィールドの後、時間フィールドの前に置くことを推奨します。
6. フィールドグループ化原則
1. 関連フィールドをグループ化
論理的に関連するフィールドをまとめて設置:
- ユーザー基本情報:
username,email,phone,avatar - 監査フィールド:
create_by,create_time,update_by,update_time - 論理取り除きフィールド:
del_flag,delete_time
- ユーザー基本情報:
データ型が似ているフィールドをグループ化:
- すべての時間フィールドをまとめる(
create_time,update_time,login_time) - すべての金額フィールドをまとめる(
order_amount,discount,pay_amount)
- すべての時間フィールドをまとめる(
2. 頻繁にクエリするフィールドを優先
- 高頻度クエリフィールドを前へ:
user_id、order_status、create_timeなど WHERE または JOIN でよく使うフィールドは、テーブル前方に設置します。 - インデックスフィールドを明示化: フィールドの物理位置はインデックス性能に影響しませんが、インデックスフィールドを前方に置くことで、デベロップメント者が重要フィールドを素早く識別できます。
付録: よく使うフィールド名と規約
| 番号 | フィールド意味 | フィールド名 | 備考 | 型 | 長さ |
|---|---|---|---|---|---|
| 1 | 分類/カテゴリ | category | カテゴリまたは分類を表すフィールド。 | VARCHAR | 128 |
| 2 | 種別 | type | 種別を表すフィールド。状態種別などでよく使われます。 | VARCHAR | 10 |
| 3 | 説明 | description | データエンティティを簡単に説明するフィールド。SQLでは varchar(512) が多く使われます。 | VARCHAR | 512 |
| 4 | 紹介 | introduction | データエンティティを詳しく紹介または説明するフィールド。 | TEXT | — |
| 5 | コード | code | 商品コード、ユーザーコードなどの一意識別コード。 | VARCHAR | 128 |
| 6 | レベル | level | レベルや権限等級などを表します。 | INT | — |
| 7 | 内容 | content | 主な内容を保存するフィールド。 | TEXT | — |
| 8 | 並び順値 | order_num | 並び順フィールド。通常はソートまたは優先度制御に使用します。 | INT | — |
| 9 | 状態 | status | 状態フィールド。有効/無効、アクティブ/凍結など。 | TINYINT | 4 |
| 10 | 承認状態 | audit_status | 承認状態。承認待ち、承認済み、拒否など。 | TINYINT | 4 |
| 11 | 承認者 | auditor_id | 承認者。通常は承認者IDまたはユーザー名。 | BIGINT | — |
| 12 | 承認日時 | audit_time | 承認の具体的な時点を記録する時間フィールド。 | DATETIME | — |
| 13 | 名称 | name | ユーザー名、プロジェクト名などを表す名称フィールド。 | VARCHAR | 128 |
| 14 | 電話番号 | phone | 電話番号フィールド。 | VARCHAR | 20 |
| 15 | メール | メールフィールド。 | VARCHAR | 100 | |
| 16 | 住所 | address | 住所フィールド。 | VARCHAR | 255 |
| 17 | 性別 | gender | 性別フィールド。値: 0=不明、1=男性、2=女性。非NULL、既定値0。 | TINYINT | 4 |
| 18 | 年齢 | age | 年齢フィールド。 | INT | — |
| 19 | 誕生日 | birthday | 生年月日フィールド。 | DATE | — |
| 20 | アバター | avatar | アバターフィールド。 | VARCHAR | 256 |
| 21 | 作る者 | create_by | 作る者名を記録します。 | VARCHAR | 32 |
| 22 | 作る者ID | creator_id | 作る者IDを記録します。 | BIGINT | — |
| 23 | 作る日時 | create_time | 作る日時を記録するフィールド。 | DATETIME | — |
| 24 | アップデート者 | update_by | 最終アップデート者名を記録します。 | VARCHAR | 32 |
| 25 | アップデート者ID | updater_id | 最終アップデート者IDを記録します。 | BIGINT | — |
| 26 | アップデート日時 | update_time | 最終アップデート日時を記録するフィールド。 | DATETIME | — |
| 27 | 取り除き者 | delete_by | 論理取り除きフィールド。レコード取り除き者名を表します。 | VARCHAR | 32 |
| 28 | 取り除き者ID | deleter_id | 論理取り除きフィールド。レコード取り除き者IDを表します。 | BIGINT | — |
| 29 | 取り除き日時 | delete_time | 論理取り除きフィールド。レコード取り除き時刻を表します。 | DATETIME | — |
| 30 | 取り除き済みか | del_flag | 論理取り除きフラグ(0: 未取り除き、1: 取り除き済み)。 | TINYINT | 1 |
| 31 | 有効か | valid_flag | 有効かどうかを表します(0: 無効、1: 有効)。 | TINYINT | 1 |
| 32 | ロック済みか | lock_flag | ロックされているかを表します(0: 未ロック、1: ロック済み)。 | TINYINT | 1 |
| 33 | 有効化済みか | enable_flag | 0は無効、1は有効を表します。 | TINYINT | 1 |
| 34 | 必須か | require_flag | フィールドが必須かを表します(0: 任意、1: 必須)。 | TINYINT | 1 |
| 35 | 備考 | remark | 補足説明または備考情報に使用します。 | VARCHAR | 512 |
| 36 | 親ID | parent_id | ツリー構造または階層関係の親ノード識別子。 | BIGINT | — |
| 37 | 子ID | child_id | ツリー構造または階層関係の子ノード識別子。 | BIGINT | — |
| 38 | パス | path | ファイルパス、URLパスなどのパス情報を保存します。 | VARCHAR | 256 |
| 39 | 関連ID | related_id | 他エンティティに関連するID。例: 注文に関連するユーザーID。 | BIGINT | — |
| 40 | 操作種別 | action_type | 操作種別。加える、取り除き、アップデートなど。 | TINYINT | 4 |
| 41 | 権限 | permission | 権限フィールド。 | VARCHAR | 100 |
| 42 | 権限グループ | role_group | 権限グループフィールド。例: ロール割り当て。 | VARCHAR | 100 |
| 43 | ファイル名 | file_name | ファイルの名称。 | VARCHAR | 128 |
| 44 | ファイルサイズ | file_size | ファイルサイズ。 | BIGINT | — |
| 45 | ファイルパス | file_path | ファイル保存パス。 | VARCHAR | 256 |
| 46 | ファイル種別 | file_type | ファイル種別。pdf、jpg、png など。 | VARCHAR | 32 |
| 47 | 期限日時 | expiry_date | データが期限切れかどうかを表す時間フィールド。 | DATETIME | — |
| 48 | タイムスタンプ | timestamp | タイムスタンプを記録します。 | DATETIME | — |
| 49 | リクエスト元 | source | リクエスト元フィールド。 | TINYINT | 4 |
| 50 | リクエストパラメーター | params | リクエストパラメーターフィールド。 | TEXT | — |
| 51 | リクエストIP | request_ip | リクエスト元IPアドレス。 | VARCHAR | 45 |
| 52 | IPアドレス | ip_address | IPアドレスを保存するフィールド。 | VARCHAR | 45 |
| 53 | バージョン番号 | version | データバージョンフィールド。バージョン番号を記録します。 | INT | — |
| 54 | 既定値か | default_flag | 既定値かどうか(0: いいえ、1: はい)。 | TINYINT | 1 |
| 55 | トリガー時刻 | trigger_time | イベントがトリガーされた時刻。 | DATETIME | — |
| 56 | 応答時刻 | response_time | 応答イベントの時刻。 | DATETIME | — |
| 57 | アクセス回数 | visit_count | アクセス回数を記録します。 | INT | — |
| 58 | 検証情報 | verification_info | 検証情報、たとえば検証コードを保存します。 | VARCHAR | 100 |
| 59 | 一意識別子 | uuid | 一意識別子。分散システムでよく使用します。 | VARCHAR | 36 |
| 60 | シリアル番号 | serial_no | 物品、注文、製品などの一意番号としてよく使用します。 | VARCHAR | 64 |
| 61 | タグ | tag | プロジェクト、ユーザー、製品などのタグ情報を記録します。 | VARCHAR | 128 |
ヒント
規約を守ることで、安定して遠くまで進めます。
