なりせなるてず

技術ブログにしたい

fuelphpのマイグレーションでvarchar型、text型にインデックスを付ける

fuelphpマイグレーション機能で苦戦したのでメモ。

環境

fuelphp : 1.7.1
PHP : 5.3.3
mysql : 5.5.34


charsetをutf8mb4にしたため普通に

\DBUtil::create_index('table', 'text_data');

とかやると

Index column size too large. The maximum column size is 767 bytes.

が出て怒られる。


やったこと

my.cnfに

innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix

を追加。
キープレフィックスの制限を大きくする(3072バイトまで)

ここまでは普通の対応なのだが、ここから荒業。
DBUtilクラスのcreate_tableメソッドにはrow_formatを指定するところが無いので、
エンジンを指定するときに無理やりいれてしまう。
公式ドキュメントを引用すると

\DBUtil::create_table(
    'users',
    array(
        'id' => array('constraint' => 11, 'type' => 'int', 'auto_increment' => true),
        'name' => array('type' => 'text'),
        'email' => array('constraint' => 50, 'type' => 'varchar'),
        'title' => array('constraint' => 50, 'type' => 'varchar', 'default' => 'mr.'),
        'text_data' => array('type' => 'text'),
        'password' => array('constraint' => 125, 'type' => 'varchar'),
    ),
    array('id'), false, 'InnoDB row_format=DYNAMIC', 'utf8_unicode_ci',array()
);

上記の’InnoDB row_format=DYNAMIC’の部分。
本来ここはストレージエンジンを指定する場所だが、ここに入れておくとうまくSQLに展開してくれた。



次にインデックスの追加
text型の場合、キーの長さを指定する。
普通に書くとエスケープ?されるのでDB::exprで囲む

\DBUtil::create_index('users', \DB::expr('text_data(1023)'), 'text_index');

こんな感じ。



これでとりあえずインデックス付けれました。
が、一つ問題があって、text型のカラムを1023バイトって指定したにもかかわらず実際に出来たテーブルを見ると

KEY `text_index` (`text_data`(768))

と768バイトでインデックスが追加されてました。

上でinnodb_large_prefixを指定してるのになんでこのバイト数なのか。。
varchar(300)のカラムとかもインデックス追加してて上記のエラーが出ないのでinnodb_large_prefixはちゃんと反映されてるはず・・・。
なのですがこれは結構調べましたが結局わかりませんでした。