最近ではあまり見られませんが、昔のデータベースのテーブル設計を見てみると
- VARCHAR(255)
という指定がちょくちょく見られます。
utf8mb4が主流の今となってはさほど見られませんが、何故でしょう?そもそもあまり理由が分かってなかったので調べてみます。
改めてVARCHAR(255)とVARCHAR(256)の壁をおさらいしてみる
varchar, 255, 256の違い
https://teratail.com/questions/96597
ここに大体の疑問とその答えが書いてあった。
MySQLでの、**文字列型のストレージ要件**は以下です。
VARCHAR(M)、VARBINARY(M)
カラム値が 0 から 255 バイトを必要とする場合は、L + 1 バイト、値が 255 バイト以上を必要とする可能性のある場合は、L + 2 バイト
上記が前提ですね。
では、なぜ255と256で1バイトの違いがでるかと言うと、**「保存されているデータのバイト数」の「表現に必要なバイト数」**が変わるからですね。
1バイトで表せるのは16進で(00~FF)です。
で255と256をぞれぞれを16進で表すと(255=FF、256=100)となって、256を表すのには2バイト必要ということになります。
ふむふむ。
カラム値が 0 から 255 バイトを必要とする場合は、L + 1 バイト、値が 255 バイト以上を必要とする可能性のある場合は、L + 2 バイト
L がVARCHARの数字。数字が255までなら+1バイト、256以上なら+2バイトとなる。
どういうことかというと、
「文字列の長さ ( L ) + 文字列の長さを記録するための入れ物」 というイメージ。
つまり
- VARCHAR(255)だと1バイト必要
- VARCHAR(255)だと2バイト必要
ということ。
その理由が上記の16進数での表記の話になる。
1文字の違いで1バイト節約できるかどうか変わるよ!という話。
データベースの文字コードに依存
ただし、VARCHARの長さは文字コードのバイト数にも依存するので、例えば文字コードがUTF-8の場合、VARCHAR(255)は765バイトの領域を確保しようとするため、VARCHAR(255)であろうと、VARCHAR(256)であろうと文字列長の管理に2バイト必要なことに変わりはありません。
これがVARCHAR(85)とVARCHAR(86)の話であればリンク先の記載の通りですが、そんな細かいことはいいんだよ、というのが趣旨かと思いますので、結局のところは気にされなくてもよいのではないかと思います。
さて、この話はデータベースの文字コードによって色々と変わってくる。
「latin1」なら1文字1バイトで前述した通りの壁が出てくる話になるが、UTF-8だと変わってくる。
utf8mb4時代の「255、256の壁」と同等なのは?
最近だと「utf8mb4」とかになるがこれは1文字4バイトとして扱う。そうするとVARCHAR(1)の時点で4バイト使用している。
これがどういうことか、というと
VARCHAR(64)と指定した時点で「4×64=256」になり「文字列の長さを記録するための入れ物」は2バイト必要になる。
VARCHAR(63)にすれば「4×63=252」で「文字列の長さを記録するための入れ物」は1バイト必要になる。
つまり文字コードが「utf8mb4」の場合、
VARCHAR(255)、VARCHAR(256)の壁ではなく、VARCHAR(63)、VARCHAR(64)の壁になる。
まとめ
VARCHAR(255)、VARCHAR(256)の壁は16進数における1バイトの表現から出た話。
1バイトの違い?どうだっていいや。となるシステムもあるし、1バイトの重みを感じるシステムもあるので知っておいて損はない。
ちなみに文字コードによって壁は変動し「utf8mb4」の場合、1バイトと2バイトの境界値は
- VARCHAR(63)、VARCHAR(64)
となる。
63文字だと中途半端すぎるので滅多にVARCHAR(63)は見ない気がするが、やってる現場は存在するのだろうか。
参考
varchar, 255, 256の違い / teratail
https://teratail.com/questions/96597
コメント