1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【VARCHAR vs TEXT】ERROR 1118 (42000): Row size too large.の対処

Posted at
エラー全文
CREATE TABLE`t1` (
    `id` INT(7) NOT NULL AUTO_INCREMENT,
    `long_text1` VARCHAR(10000) NOT NULL,
    `long_text2` VARCHAR(10000) NOT NULL,
    `long_text3` VARCHAR(10000) NOT NULL,
    PRIMARY KEY (`id`)
);

ERROR 1118 (42000): Row size too large.
The maximum row size for the used table type, not counting BLOBs, is 65535.
This includes storage overhead, check the manual.
You have to change some columns to TEXT or BLOBs

/*
Google翻訳
エラー1118(42000):行サイズが大きすぎます。
使用されるテーブルタイプの最大行サイズは、BLOBを除いて、65535です。
これにはストレージのオーバーヘッドが含まれます。マニュアルを確認してください。
一部の列をTEXTまたはBLOBに変更する必要があります。
*/

結論

エラーメッセージの通り、VARCHAR型カラムをTEXT型カラムに変更することで解消されました。

もう少し細かく見る

###エラーの原因
MySQLテーブルには行サイズの制限があります。

行サイズ制限
MySQL テーブルの内部表現の最大行サイズは 65,535 バイトです。

参考:8.4.7 テーブルカラム数と行サイズの制限

注意すべきは、65,535バイトの制限がカラム全体の合計サイズに対して設けられているということです。
CREATE TABLE文の実行時点でカラムの合計バイト数が65,535バイトを超えていたので、上記エラーが発生しました。

###VARCHAR型とTEXT型それぞれが確保するバイト数について

#####VARCHAR型
VARCHARカラムには可変長の文字列を設定します。
INT型などでは型名に続く( )でバイト数を指定しますが、CHAR/VARCHAR型では( )に文字数を指定します。

CREATE TABLE`t1` (
    `id` INT(7) NOT NULL AUTO_INCREMENT,
    `long_text1` VARCHAR(10000) NOT NULL, --「10,000文字入る」であって「10,000バイト確保してる」ではないので注意!
);

今回はDBに登録する際の文字コードはUTF-8(1文字3バイトの文字コード)を使用していたので、
上記の例ではこのカラムだけで(10,000文字 * 3バイト) + VARCHARのコード長を示す2バイト = 30,002バイトを確保してしまっていることになります。

#####TEXT型
再度リファレンスマニュアルより。

BLOB および TEXT のカラムは、行サイズ制限に 9 から 12 バイトのみ寄与します。これは、その内容が行の他の部分とは別に格納されるためです。

VARCHAR型が入力された文字列をテーブル上にそのまま保存するのに対し、TEXT型ではポインタのみをテーブルに保持しデータ自体は別の場所に格納します。

CREATE TABLE`t1` (
    `id` INT(7) NOT NULL AUTO_INCREMENT,
    `long_text1` TEXT NOT NULL, -- 10,000文字格納してもテーブル上は9~12バイトのみ確保される
);

###本当にこの対応でいいの?

#####TEXT型のデメリット

  • データを取り出すときに一度参照を挟むため、データを直接格納しているVARCHAR型よりは処理に時間がかかる(未検証)
  • インデックスを貼るときに長さを指定する必要があり、考慮することが増える

#####そもそもVARCHAR(4000)みたいな行が複数存在するテーブルは良い設計でない可能性が高い
調べれば調べるほど、処理速度のことを考えると基本的にはTEXT型の使用は避けるべきというのが一般論のようです。VARCHAR型を使用できるようににテーブル設計を見直してみます...。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?