🦍

なぜVARCHARの文字数指定を255にするのか!?

2024/05/07に公開

結論

可変長型には、値に含まれるバイト数を示す長さプリフィクスというものがあり、

  • 255バイト以下なら 1バイト長
  • 255より大きいなら 2バイト長

よって1文字が1バイトの文字コードなら、 255文字まで長さプリフィクスを1バイトに抑えられる


きっかけ

新卒研修でDB設計をしている際に、VARCHAR(255)とあり、この255は何なのか気になってしまった。
だって調べたら65,535まで指定って書いてある!
わざわざ255にする必要あるのかな・・・?

VARCHAR カラム内の値は可変長の文字列です。 長さは 0 から 65,535 までの値で指定できます。
公式ドキュメントより

そもそも指定できるって何?文字数を?バイト数を?

VARCHAR カラム内の値は可変長の文字列です。 長さは 0 から 65,535 までの値で指定できます。 VARCHAR カラムの有効な最大長は、最大行サイズ (65,535 バイト、すべてのカラムで共有される) と使用される文字セットによって決まります。
公式ドキュメントより

最初、65,535まで指定できるなら、65,535文字入ると思いましたが、違うようです。
どうやら文字セットが関係している模様

VARCHAR または VARBINARY カラムに格納できる有効な最大バイト数は最大行サイズ (65,535 バイト、すべてのカラムで共有される) によって決まります。 複数バイト文字を格納する VARCHAR カラムの場合、文字の有効な最大数は少なくなります。 たとえば、utf8mb4 文字には文字ごとに最大 4 バイトが必要な場合があるため、utf8mb4 文字セットを使用する VARCHAR カラムは 16,383 文字まで宣言できます。

これによると・・・

  • VARCHARには65,535バイトまで入る
  • 最大文字数は、文字コードによって変わる
  • 指定できるのは、文字コードを考慮した文字数

例えば latin1 という1文字が1バイトの文字コードがあります。
この場合、

655,35バイト\div1文字1バイト=65,535文字

なので65,535文字まで入ります。

しかし、utf8mb4では文字によって1~4バイトになります。
仮に全ての文字が4バイトと仮定すると、

655,35バイト\div1文字4バイト=16,383文字

で16,383文字まで入ります。

指定できるのが文字数とわかったところで次の疑問へ。

255文字を指定する理由は?

まず、VARCHARは可変長の文字列型であるという点が重要です。

VARCHAR カラム内の値は可変長の文字列です。
公式ドキュメントより

可変長というのは、簡単に言うとデータに合わせて縮む感じです。
こちらの記事が参考になります。

https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0041

可変長の文字列型は、データの先頭に、値のバイト数を表すみたいです。

1 バイトまたは 2 バイト長のプリフィクスの付いたデータとして格納されます。
公式ドキュメントより

image.png

値のバイト数 プリフィクス
0~255 1バイト
256~ 2バイト

つまりこのプリフィクスが、値のバイト数が255を境目に、
1バイトになるか2バイトになるか、という違いみたいです。

1バイト減らせてお得ですよね。

でも1文字が1ビットならね!

VARCHAR(255)を指定し、255文字まで入るようにします。

例えばlatin1 という1文字が1バイトの文字コードなら、

255文字\times1文字あたり1バイト=255バイト

になり、プリフィクスを1バイトに抑えることができます。

しかしながらutf8mb4は、先ほどもお伝えした通り、1~4文字です。
例えば全て4バイト文字を入れている場合、

255文字\times1文字あたり4バイト=1020バイト

ですので、長さプリフィクスは2バイトになってしまいます。
このことから、utf8mb4においてVARCHAR(255)は必ずプリフィクスを1バイトに抑えることはできません。

プリフィクスの区切りはどこが良いか?

以上のようにプリフィクスが1バイトか2バイトになる区切りは、1文字あたりのバイト数によって変動します。

例えばもし全て1文字4バイトであるならば、

255バイト\div1文字あたり4バイト=63.75文字

63文字を超えるとプリフィクスは2バイト必要なので、この条件の場合はVARCHAR(63)にするべきです。
しかし実際には、全て4バイトの文字とは限りません。
当然1~4文字の混在しているケースがあります。この場合実際のデータのバイト数によるため、明確な一定の区切りは分かりません。

条件 プリフィクスが1になる文字数
全て1バイトなら 255文字まで
全て2バイトなら 127文字まで
全て3バイトなら 85文字まで
全て4バイトなら 63文字まで
混在している わからない!!

結論

255文字の指定は、1文字1バイトなら長さプリフィクスを減らせるから良い。
utf8mb4において255文字の指定は、必ずしもプリフィックスを減らせるわけではない。

Discussion