なぜVARCHARの文字数指定を255にするのか!?
結論
可変長型には、値に含まれるバイト数を示す長さプリフィクスというものがあり、
- 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バイトの文字コードがあります。
この場合、
なので65,535文字まで入ります。
しかし、utf8mb4では文字によって1~4バイトになります。
仮に全ての文字が4バイトと仮定すると、
で16,383文字まで入ります。
指定できるのが文字数とわかったところで次の疑問へ。
255文字を指定する理由は?
まず、VARCHARは可変長の文字列型であるという点が重要です。
VARCHAR カラム内の値は可変長の文字列です。
公式ドキュメントより
可変長というのは、簡単に言うとデータに合わせて縮む感じです。
こちらの記事が参考になります。
可変長の文字列型は、データの先頭に、値のバイト数を表すみたいです。
1 バイトまたは 2 バイト長のプリフィクスの付いたデータとして格納されます。
公式ドキュメントより
値のバイト数 | プリフィクス |
---|---|
0~255 | 1バイト |
256~ | 2バイト |
つまりこのプリフィクスが、値のバイト数が255を境目に、
1バイトになるか2バイトになるか、という違いみたいです。
1バイト減らせてお得ですよね。
でも1文字が1ビットならね!
VARCHAR(255)
を指定し、255文字まで入るようにします。
例えばlatin1 という1文字が1バイトの文字コードなら、
になり、プリフィクスを1バイトに抑えることができます。
しかしながらutf8mb4は、先ほどもお伝えした通り、1~4文字です。
例えば全て4バイト文字を入れている場合、
ですので、長さプリフィクスは2バイトになってしまいます。
このことから、utf8mb4においてVARCHAR(255)
は必ずプリフィクスを1バイトに抑えることはできません。
プリフィクスの区切りはどこが良いか?
以上のようにプリフィクスが1バイトか2バイトになる区切りは、1文字あたりのバイト数によって変動します。
例えばもし全て1文字4バイトであるならば、
63文字を超えるとプリフィクスは2バイト必要なので、この条件の場合はVARCHAR(63)
にするべきです。
しかし実際には、全て4バイトの文字とは限りません。
当然1~4文字の混在しているケースがあります。この場合実際のデータのバイト数によるため、明確な一定の区切りは分かりません。
条件 | プリフィクスが1になる文字数 |
---|---|
全て1バイトなら | 255文字まで |
全て2バイトなら | 127文字まで |
全て3バイトなら | 85文字まで |
全て4バイトなら | 63文字まで |
混在している | わからない!! |
結論
255文字の指定は、1文字1バイトなら長さプリフィクスを減らせるから良い。
utf8mb4において255文字の指定は、必ずしもプリフィックスを減らせるわけではない。
Discussion