ただのメモ。

GrowthForecast のテーブルを作ろうと以下の DDL を打ったら失敗した。# 正確には、GF は自動で作ろうとしてくれるが、その時に失敗していた。

CREATE TABLE IF NOT EXISTS complex_graphs (
    id           INT UNSIGNED NOT NULL AUTO_INCREMENT,
    service_name VARCHAR(255) NOT NULL COLLATE utf8_bin,
    section_name VARCHAR(255) NOT NULL COLLATE utf8_bin,
    graph_name   VARCHAR(255) NOT NULL COLLATE utf8_bin,
    number       float UNSIGNED NOT NULL DEFAULT 0,
    description  VARCHAR(255) NOT NULL DEFAULT '',
    sort         INT UNSIGNED NOT NULL DEFAULT 0,
    meta         TEXT,
    created_at   INT UNSIGNED NOT NULL,
    updated_at   INT UNSIGNED NOT NULL,
    PRIMARY KEY (id),
    UNIQUE  (service_name, section_name, graph_name)
)  ENGINE=InnoDB DEFAULT CHARSET=utf8;

エラーメッセージは次のようなもの

ERROR 1071 (42000): Specified key was too long; max key length is 1000 bytes

あれ、なんで今まで大丈夫だったんだ?と思ったので調べた。1000 bytes 制限が出るのは、MyISAM の場合らしい。

MyISAM の場合、複合インデックスで全てのカラムの byte 数を合計した結果が 1000 bytes を超えるとダメで、(255 + 255 + 255) * 3 (utf8) で 1000 bytes 超えたから出たようだ。

つまり、InnoDB プラグインかなにかがちゃんと設定できていなくて、InnoDB で table 作ったつもりが、MyISAM になってしまっていたということだな。


ちなみに InnoDB の場合は 767 byets 制限のメッセージが出る事がある。

ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

こちらは、複合インデックスでもカラムそれぞれの制限値[1][2]になっているようだ。今回の場合は 255 * 3 (utf8) = 765 bytes なので、制限を超えずちゃんとテーブルを作れる。

なお、mysql5.6 にして utf8mb4 に使おうとすると、255 * 4 (utf8mb4) = 1020 bytes となり、制限を超えてしまうが、その場合は、innodb_large_prefix というオプションを ON にすると、3072 bytes まで扱える。

[1] http://blog.kamipo.net/entry/2012/11/13/102024 ひとつのカラムのキープレフィックスの最大値が767バイト
[2] http://treeapps.hatenablog.com/entry/20110508/p2 カラム分割も制限をかわす1つのテクニックになりうる