MySQL データベース設計規約
適用条件
- データベースのテーブル構造を設計する
- フィールドの型と長さを定義する
- インデックスを作成する
- テーブル名とフィールド名を付ける
Part 1: 命名規約
データベース名
| 規則 | 説明 |
|---|
| 小文字 | youlai_admin |
| アンダースコアで区切る | キャメルケースは使用しない |
| 業務プレフィックス | youlai_ |
テーブル名
| 種類 | プレフィックス | 例 |
|---|
| システムテーブル | sys_ | sys_user, sys_role |
| 業務テーブル | biz_ | biz_order, biz_product |
| 関連テーブル | rel_ またはメインテーブルのプレフィックス | sys_user_role, rel_user_dept |
| 設定テーブル | cfg_ | cfg_dict, cfg_config |
| ログテーブル | log_ | log_login, log_operation |
フィールド名
| 種類 | 規則 | 例 |
|---|
| 主キー | id | id |
| 外部キー | テーブル名 + _id | user_id, dept_id |
| 名前 | xxx_name | user_name, dept_name |
| 状態 | status | status |
| 種類 | xxx_type | menu_type, log_type |
| 時刻 | xxx_time | create_time, login_time |
| ブール値 | is_xxx | is_deleted, is_enabled |
| 件数 | xxx_count | login_count, view_count |
| 並び順 | sort または order_num | sort |
インデックス名
| 種類 | プレフィックス | 例 |
|---|
| 主キー | pk_ | pk_user |
| ユニークインデックス | uk_ | uk_username |
| 通常のインデックス | idx_ | idx_dept_id |
| 複合インデックス | idx_ | idx_dept_status |
| 全文インデックス | ft_ | ft_content |
Part 2: フィールド型の規約
主キー
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键'
文字列型
| 用途 | 型 | 長さ |
|---|
| ユーザー名 | VARCHAR | 50 |
| ニックネーム | VARCHAR | 50 |
| パスワード(暗号化後) | VARCHAR | 100 |
| 電話番号 | VARCHAR | 20 |
| メールアドレス | VARCHAR | 100 |
| URL | VARCHAR | 500 |
| タイトル | VARCHAR | 200 |
| 概要 | VARCHAR | 500 |
| 詳細な説明 | TEXT | - |
| JSON データ | JSON | - |
数値型
| 用途 | 型 | 説明 |
|---|
| 主キー/ID | BIGINT | 20 桁 |
| 外部キー | BIGINT | 関連する主キーと同じ型 |
| 数量/件数 | INT | - |
| 金額(最小通貨単位) | BIGINT | 浮動小数点の精度問題を回避 |
| 並び順番号 | INT | - |
| 状態 | TINYINT | 0/1/2 |
| 種類 | TINYINT | 列挙値 |
| パーセンテージ | DECIMAL(5,2) | 0.00-100.00 |
時刻型
| 用途 | 型 | 説明 |
|---|
| 作成時刻 | DATETIME | create_time |
| 更新時刻 | DATETIME | update_time |
| 日付 | DATE | birth_date |
| タイムスタンプ | BIGINT | ミリ秒単位 |
ブール型
`is_deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除(0否 1是)'
`is_enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用(0否 1是)'
Part 3: 共通フィールド
すべてのテーブルに必須のフィールド
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` BIGINT UNSIGNED DEFAULT NULL COMMENT '创建人',
`update_by` BIGINT UNSIGNED DEFAULT NULL COMMENT '更新人',
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志(0未删除 1已删除)',
PRIMARY KEY (`id`)
任意のフィールド
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
`version` INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
`tenant_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '租户ID',
Part 4: インデックスの規約
インデックスの原則
| 原則 | 説明 |
|---|
| 最左プレフィックス | 複合インデックスはクエリの順序に合わせて作成する |
| 高い選択性 | 区別度の高い列を選択する |
| 数を制限する | 1 テーブルあたりのインデックスは 5 個以下にする |
| 複合を優先する | 複合インデックスは複数の単一列インデックスより優先する |
必須のインデックス
-- 主键索引
PRIMARY KEY (`id`)
-- 外键索引
INDEX `idx_dept_id` (`dept_id`)
-- 状态索引(常用于筛选)
INDEX `idx_status` (`status`)
-- 创建时间索引(常用于排序)
INDEX `idx_create_time` (`create_time`)
-- 唯一索引(业务唯一字段)
UNIQUE INDEX `uk_username` (`username`)
複合インデックス
-- 组合索引:部门 + 状态
INDEX `idx_dept_status` (`dept_id`, `status`)
-- 组合索引:用户 + 创建时间
INDEX `idx_user_time` (`user_id`, `create_time`)
インデックスで避けること
| 避けること | 理由 |
|---|
LIKE '%xxx%' | 前方一致ではない曖昧検索はインデックスを使用しない |
OR 条件 | インデックスを使用しない場合があるため、UNION に変更する |
| 関数の適用 | WHERE YEAR(create_time) = 2024 はインデックスを使用しない |
| 型変換 | 文字列と数値の比較では暗黙的な型変換が行われる |
NOT IN | NOT EXISTS または LEFT JOIN ... IS NULL に変更する |
Part 5: テーブル設計規約
ユーザーテーブルの例
CREATE TABLE `sys_user` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
`nickname` VARCHAR(50) NOT NULL COMMENT '昵称',
`mobile` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`gender` TINYINT NOT NULL DEFAULT 0 COMMENT '性别(0未知 1男 2女)',
`avatar` VARCHAR(500) DEFAULT NULL COMMENT '头像URL',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(1正常 0禁用)',
`dept_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` BIGINT UNSIGNED DEFAULT NULL COMMENT '创建人',
`update_by` BIGINT UNSIGNED DEFAULT NULL COMMENT '更新人',
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志(0未删除 1已删除)',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_username` (`username`),
INDEX `idx_dept_id` (`dept_id`),
INDEX `idx_status` (`status`),
INDEX `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
関連テーブルの例
CREATE TABLE `sys_user_role` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
`role_id` BIGINT UNSIGNED NOT NULL COMMENT '角色ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_user_role` (`user_id`, `role_id`),
INDEX `idx_role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户角色关联表';
Part 6: フィールドのデフォルト値
| フィールド型 | デフォルト値 | 説明 |
|---|
| 文字列 | NULL または '' | 任意項目には NULL を使用する |
| 数値 | 0 | - |
| ブール値 | 0 または 1 | 業務に応じて設定する |
| 時刻 | CURRENT_TIMESTAMP | - |
| 外部キー | NULL | 任意の関連項目 |
NULL と NOT NULL
| 用途 | 選択 |
|---|
| 必須フィールド | NOT NULL |
| 任意フィールド | NULL |
| 外部キー(任意) | NULL |
| 状態フィールド | NOT NULL DEFAULT 1 |
Part 7: 文字セットとエンジン
文字セット
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
| 設定 | 説明 |
|---|
utf8mb4 | 4 バイト文字(絵文字)をサポートする |
utf8mb4_unicode_ci | 大文字と小文字を区別せずにソートする |
ストレージエンジン
ENGINE=InnoDB
| エンジン | 適用場面 |
|---|
| InnoDB | トランザクション、外部キー、行ロック |
| MyISAM | 読み取り専用、全文インデックス(旧バージョン) |
| Memory | 一時テーブル、キャッシュ |
Part 8: SQL の記述規約
SELECT
-- ✅ 指定字段
SELECT id, username, nickname FROM sys_user WHERE status = 1;
-- ❌ 避免 SELECT *
SELECT * FROM sys_user;
-- ✅ 分页查询
SELECT id, username FROM sys_user WHERE status = 1 LIMIT 0, 20;
-- ✅ 批量插入
INSERT INTO sys_user (username, nickname) VALUES ('user1', '用户1'), ('user2', '用户2');
UPDATE
-- ✅ 带 WHERE 条件
UPDATE sys_user SET nickname = '新昵称' WHERE id = 1;
-- ✅ 乐观锁
UPDATE sys_user SET nickname = '新昵称', version = version + 1 WHERE id = 1 AND version = 1;
-- ❌ 避免全表更新
UPDATE sys_user SET status = 0;
DELETE
-- ✅ 逻辑删除
UPDATE sys_user SET deleted = 1 WHERE id = 1;
-- ✅ 物理删除(慎用)
DELETE FROM sys_user_role WHERE user_id = 1;
Part 9: パフォーマンス最適化
クエリの最適化
| 最適化項目 | 説明 |
|---|
SELECT * を避ける | 必要なフィールドのみを検索する |
LIKE '%xxx%' を避ける | LIKE 'xxx%' または全文インデックスを使用する |
| 大きな OFFSET を避ける | LIMIT 10000, 20 はカーソルページネーションに変更する |
COUNT(*) を避ける | 大規模テーブルではキャッシュまたは推定値を使用する |
| バッチ処理 | 1 件ずつのループ処理の代わりに一括挿入/更新を行う |
テーブル設計の最適化
| 最適化項目 | 説明 |
|---|
| 垂直分割 | 大きなフィールドを拡張テーブルに分割する |
| 水平分割 | 大規模テーブルをルールに基づいて分割する |
| 適度な冗長化 | 関連クエリを減らす |
| 履歴データのアーカイブ | アクセス頻度の低いデータを移行する |
Part 10: 設計チェックリスト