MEDIUMINT徹底解説:3バイト整数の仕様・利点・注意点と実務での使いどころ

概要:MEDIUMINTとは何か

MEDIUMINTは、MySQLやMariaDBで利用できる整数型の一つで、3バイト(24ビット)で整数を格納します。標準SQLのデータ型には含まれないMySQL系の拡張型で、保存可能な値の範囲やストレージ効率に特徴があります。大量データを扱う環境でINT(4バイト)よりも省メモリ化を図りたい場合に採用が検討されますが、互換性や将来の拡張性を踏まえた判断が必要です。

ストレージサイズと数値範囲

MEDIUMINTの主要スペックは次の通りです。

  • ストレージサイズ:3バイト(24ビット)
  • 符号付き(SIGNED)範囲:-8,388,608 ~ 8,388,607(-2^23 ~ 2^23-1)
  • 符号なし(UNSIGNED)範囲:0 ~ 16,777,215(0 ~ 2^24-1)

この範囲は、例えばユーザーIDや製品コードなどが1700万未満に収まるケースでは問題なく利用できますが、将来的にレコード数が増える可能性がある場合は注意が必要です。

SQLでの指定方法とオプション

基本的なカラム定義は以下のようになります。

CREATE TABLE example ( id MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY );
CREATE TABLE example2 ( cnt MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 );

ポイント:

  • AUTO_INCREMENTはMEDIUMINTでも利用可能です。ただし増分で上限を超えるとエラーになります。
  • DEFAULT、NOT NULL、UNSIGNEDなどのオプションは通常通り利用できます。
  • かつてはMEDIUMINT(M)のように“M”で表示幅を指定できましたが、最近のMySQL系バージョンでは表示幅(display width)の扱いが変更されており、非推奨または無視される場合があります。環境のドキュメントを確認してください。

INTやSMALLINTとの比較

主要な整数型との比較:

  • TINYINT:1バイト。範囲(SIGNED)-128〜127、(UNSIGNED)0〜255。フラグや小さいカウンタ向け。
  • SMALLINT:2バイト。範囲(SIGNED)-32,768〜32,767、(UNSIGNED)0〜65,535。
  • MEDIUMINT:3バイト。前述の通り。
  • INT:4バイト。範囲(SIGNED)-2,147,483,648〜2,147,483,647、(UNSIGNED)0〜4,294,967,295。最も汎用的でデフォルト採用例が多い。

MEDIUMINTはINTより1バイト小さく、1レコードあたりのストレージとインデックスサイズを縮小できます。大量レコードのテーブルで列が多数ある場合やインデックスが大きい場合、合計で大きな節約になります。ただし将来の拡張性を犠牲にしないことが重要です。

パフォーマンスとストレージ面での考慮

MEDIUMINTを選ぶ主な理由はストレージとI/Oの節約です。以下が考慮点です。

  • ディスク/メモリ使用量:3バイトは4バイトよりも小さいため行幅が狭くなり、ページ当たりの行数が増加。結果としてI/O数が減り、キャッシュ効率が上がる可能性があります。
  • インデックス:インデックスキーにMEDIUMINTを使えば、Bツリーのノード数や深さが小さくなり検索が高速化される場合があります。
  • CPU処理:多くの場合、整数演算はCPUで効率よく行われます。演算速度差は通常わずかですが、アラインメントやCPUの最適化によっては若干影響が出ることもあります。
  • アラインメント/パディング:ストレージエンジンや行フォーマットによっては内部でパディングや格納方法が異なるため、必ずしも単純に1バイト分の節約がそのまま全体のサイズ縮小につながるとは限りません。InnoDBでは行フォーマットやカラム順序、可変長カラムの存在などが総体的なサイズに影響します。

互換性と移植性の問題

MEDIUMINTはMySQL/MariaDBの拡張型で、他のDBMS(例:PostgreSQL、SQL Server、Oracle)には直接同等の型は存在しません。移行やレプリケーション、外部ツールとの連携を考えると次の点に注意してください。

  • 移行時:PostgreSQLなどにデータを移すときはINTまたはBIGINTにマッピングするのが一般的です。逆に外部DBからMySQLに取り込む際に型の差に注意。
  • ORM/フレームワーク:一部ORMはMEDIUMINTを明示的に扱えない場合があり、INTとして扱われることがあります。マイグレーション生成やスキーマ同期で差異が生じる可能性があります。
  • バックアップ/復元:mysqldumpなどは型情報を保存しますが、別DBMSへ移す際には型マッピングが必要です。

運用上の注意点と落とし穴

MEDIUMINTを導入する際の具体的な注意点:

  • 将来の上限超過:IDに使う場合、当初は十分でも将来的に上限を超えるとアプリケーション障害となるため、成長見込みをしっかり評価してください。
  • 既存データ型の変更:INTからMEDIUMINTへALTER TABLEで変更する場合、既存データが範囲内かを事前にチェックする必要があります。範囲外の値が存在する場合、ALTERは失敗またはデータが切り捨てられる危険があります。
  • レプリケーション/互換性:レプリケーションスキーマの齟齬があると問題になるため、マスターとスレーブでスキーマを一致させてください。
  • 表示幅の扱い:以前のMySQLではMEDIUMINT(M)のMで表示幅を指定できましたが、最近のバージョンではこの表示幅が無視されるか非推奨になっているため、ZEROFILLなどと組み合わせて利用する際は動作を確認してください。

設計上のベストプラクティス

MEDIUMINTを採用するかどうか判断するための実務的ガイドライン:

  • 採用基準:IDやカウントが最大で1,000万〜1,600万未満に収まる明確な見通しがある場合に検討する。
  • 将来性の評価:成長予測が不確実ならばINT(4バイト)を選んでおく方が無難。余裕を取ることで将来のALTERを避けられます。
  • モニタリング:AUTO_INCREMENTの現在値やテーブルのレコード数を監視して上限に近づいたらアラートを出す運用を整備する。
  • マイグレーション検証:schema変更は開発環境で検証。ALTER TABLEの実行時間やロック影響を考慮し、オンラインDDLツール(pt-online-schema-changeなど)を利用することも検討。

実例とユースケース

MEDIUMINTが適している例:

  • コンテンツ管理システムの投稿ID(総投稿数が数百万〜数千万に収まる見込みの場合)
  • ローカルサービスのユーザーID(地域限定やクローズドなサービスでユーザ数が1,600万未満)
  • センサーデータのカウンタや日次集計のインデックス列(上限が明確な場合)

適していない例:

  • グローバルサービスのユーザーID(数千万〜数億規模が見込まれる場合)
  • 将来的な機能拡張や他システムと統合を前提とした主要キー

変更手順の例:INT→MEDIUMINT

既存テーブルのカラムをINTからMEDIUMINTに変更する場合の基本例(MySQL):

-- 範囲チェック
SELECT COUNT(*) FROM tbl WHERE id < -8388608 OR id > 8388607;
-- 問題なければ実行(例:署名あり)
ALTER TABLE tbl MODIFY COLUMN id MEDIUMINT NOT NULL AUTO_INCREMENT;
-- 署名なしの場合
ALTER TABLE tbl MODIFY COLUMN id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT;

注意:ALTER TABLEはテーブルのサイズによって時間とロック影響が大きくなります。可能ならスケジュールされたメンテナンスやオンラインALTERを利用してください。

実務的な判断まとめ

MEDIUMINTはストレージやインデックスの節約を通じてパフォーマンス改善に寄与するケースがありますが、採用にあたってはデータ成長の見積もり、運用監視、移植性の問題を十分に検討する必要があります。一般的には次の方針が実務的です。

  • 短期〜中期のデータ量が確実にMEDIUMINTの範囲内で収まるなら採用を検討する。
  • 不確実性が高い場合はINTを選んで拡張性を確保する。
  • 既に大量レコードがありストレージ最適化が急務なら、テーブル単位で影響を精査したうえでMEDIUMINTへ変更する。

結論

MEDIUMINTは3バイトで格納できる有用な整数型で、適切に使えばディスクとI/Oの効率化に役立ちます。一方で将来のスケールや他システムとの互換性を考慮すると安易な採用は避けるべきです。設計段階で用途とスケールを見極め、監視やマイグレーション計画を伴った上で使うのが賢明です。

参考文献