技術関係

文字コードutf8mb4環境下でのVARCHAR(255)の壁に相当するのはVARCHAR(63)という話

最近ではあまり見られませんが、昔のデータベースのテーブル設計を見てみると

  • VARCHAR(255)

という指定がちょくちょく見られます。

2023年にはめったに見られませんが、何故でしょう?そもそもあまり理由が分かってなかったので調べてみます。

スポンサーリンク
スポンサーリンク

改めて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

コメント

タイトルとURLをコピーしました