MySQLにおけるDDLの完全ガイド:データベース構造の設計と管理

DDLとは何か:データベースの基盤を形成する言語

MySQLにおいて、DDL(Data Definition Language)はデータベースの構造そのものを定義・操作するためのSQLサブセットです。テーブル、データベース、インデックスといったオブジェクトの作成、変更、削除に用いられ、アプリケーションのデータモデルを物理的に実現する役割を担います。DML(データ操作言語)が「何を」扱うかに注力するのに対し、DDLは「どのように」データを格納するかを決定します。

DDLの主な特性

  • 構造指向:対象はデータではなくスキーマ(例:テーブル定義、カラム型)です。
  • 即時反映:トランザクション内で実行されても、DDL文は暗黙的にコミットされ、ロールバックできません。
  • ロックの発生:特にALTER TABLEは長時間テーブルロックをかけ、運用中のシステムに影響を与える可能性があります。

データベースの管理

まず、データベース自体に対するDDL操作を見ていきます。すべての表はデータベース内に属するため、最初のステップとして適切なデータベースを作成することが重要です。

データベースの作成

以下の構文で新しいデータベースを生成できます。

CREATE DATABASE IF NOT EXISTS app_data
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;

この例では、app_dataという名前のデータベースを作成し、絵文字も含む多言語対応のためにutf8mb4文字セットと厳密な照合順序を指定しています。IF NOT EXISTSを付けることで、既に存在する場合でもエラーを回避できます。

属性の変更

既存のデータベースの文字セットや照合順序を後から変更するには以下を使用します。

ALTER DATABASE app_data 
DEFAULT CHARACTER SET utf8mb4 
DEFAULT COLLATE utf8mb4_general_ci;

ただし、この操作はスキーマレベルの設定を変えるだけであり、すでに作成されたテーブルには自動的には反映されない点に注意が必要です。

データベースの削除

不要になったデータベースは次のように削除します。

DROP DATABASE IF EXISTS temp_db;

警告: この操作は破壊的であり、内部のすべてのテーブルとデータが永久に失われます。本番環境では極めて慎重に実行してください。

テーブルの定義と変更

テーブルはDDLの中で最も頻繁に操作されるオブジェクトです。設計段階での正確な定義と、運用中における安全な変更が求められます。

テーブル作成のベストプラクティス

以下の例は、ユーザー情報を管理するための堅牢なテーブル定義です。

CREATE TABLE user_profile (
    user_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    login_name VARCHAR(64) NOT NULL UNIQUE,
    contact_number CHAR(13) COMMENT '国際フォーマット(+8190XXXXXXX)',
    birth_date DATE,
    gender ENUM('M', 'F', 'O') DEFAULT 'O',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_login (login_name),
    INDEX idx_contact (contact_number)
) ENGINE=InnoDB 
  DEFAULT CHARSET=utf8mb4 
  COMMENT='ユーザープロファイル情報';

ポイント解説:

  • BIGINTを使用することで、将来的なスケールを見越した主キー設計が可能です。
  • ENUM型により、性別の値域を明示的に制限しています。
  • ON UPDATE CURRENT_TIMESTAMPにより、更新時にタイムスタンプが自動更新されます。
  • 必要なカラムにインデックスを事前に定義し、検索性能を確保しています。

テーブル構造の動的変更

運用中にスキーマを変更するにはALTER TABLEを使用します。代表的なパターンを紹介します。

新規カラムの追加

ALTER TABLE user_profile 
ADD COLUMN last_login DATETIME NULL AFTER updated_at;

カラムの型と制約の変更

ALTER TABLE user_profile 
MODIFY COLUMN contact_number VARCHAR(20) NULL;

カラム名の変更

ALTER TABLE user_profile 
CHANGE COLUMN login_name account_id VARCHAR(64) NOT NULL;

複合インデックスの追加

ALTER TABLE user_profile 
ADD INDEX idx_search_criteria (account_id, gender);

不要なカラムの削除

-- 注意:復元不能!
ALTER TABLE user_profile DROP COLUMN temp_field;

テーブルの削除とデータ初期化

テーブル自体を削除する場合は次の通りです。

DROP TABLE IF EXISTS legacy_table;

一方、データのみを消去して構造を残したい場合はTRUNCATEを使います。

TRUNCATE TABLE user_profile;

TRUNCATEDELETE FROMよりも高速かつ効率的ですが、条件付き削除はできず、AUTO_INCREMENTカウンタもリセットされる点に注意してください。

インデックスの管理

インデックスはクエリ性能に直接影響を与えるため、適切な設計と保守が不可欠です。

インデックスの作成

既存のテーブルに対してインデックスを追加する場合、以下の形式で記述します。

-- 単一カラムの通常インデックス
CREATE INDEX idx_birth_date ON user_profile(birth_date);

-- 一意制約付きインデックス(重複禁止)
CREATE UNIQUE INDEX uk_account_id ON user_profile(account_id);

-- 複数カラムのインデックス(最左一致則に注意)
CREATE INDEX idx_composite ON user_profile(gender, created_at DESC);

インデックスの削除

使用されていないインデックスは書き込み性能を低下させるため、定期的に見直す必要があります。

DROP INDEX idx_temporary ON user_profile;

インデックスの確認方法

現在のインデックス構成を確認するには以下を実行します。

SHOW INDEX FROM user_profile;

出力結果にはインデックス名、列名、一意性、基数などが含まれ、チューニングの参考になります。

実践における推奨事項

安全性の確保

  • バックアップの取得:重要なDDL操作前には必ずダンプを取得しましょう(mysqldumpなど)。
  • ステージング環境での検証:本番と同じスキーマを持つテスト環境で事前に動作確認を行ってください。
  • 外部キー制約の確認:関連するテーブルがある場合、参照整合性に配慮した順序で操作を行います。

パフォーマンスへの配慮

  • ピーク時間帯の避けるALTER TABLEは長時間ロックを発生させるため、夜間などの閑散期に実施します。
  • オンラインDDLの活用:MySQL 5.6以降では一部のALTER操作がオンラインで可能になっています(例:ALGORITHM=INPLACE)。
  • 過剰なインデックスの回避:インデックスは読み取りを高速化する代わりに、INSERT/UPDATE/DELETEのコストを増加させます。

バージョン互換性

異なるMySQLバージョン間ではDDLの挙動が異なることがあります。たとえば:

  • MySQL 8.0ではRENAME COLUMNがサポートされていますが、5.7以前ではCHANGE COLUMNを使う必要があります。
  • 8.0からはデフォルト文字セットがutf8mb4となりました。

まとめ

DDLはデータベースの土台を築く強力なツールであり、その使い方一つでシステム全体の信頼性と性能が大きく変わります。本稿では、データベースからテーブル、インデックスに至るまでの主要なDDL文とその実践的な利用法を解説しました。実際の開発現場では、単なる構文知識だけでなく、影響範囲の予測、リスク管理、チーム間の連携も重要です。常に「構造の変更はシステム全体に波及する」という意識を持ちながら、計画的にDDL操作を行うことをおすすめします。

タグ: MySQL DDL データベース設計 CREATE TABLE ALTER TABLE

6月22日 21:55 投稿