VARCHAR(255)にするとなぜ良いの？

:::note  warn
**前提**
- MySQL 8.0
- VARCHARのお話です！
:::

### 結論
可変長型には、値に含まれるバイト数を示す長さプリフィクスというものがあり、
 - 255バイト以下なら 1バイト長
 - 255より大きいなら 2バイト長

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

---

### きっかけ
新卒研修でDB設計をしている際に、VARCHAR(255)とあり、この255は何なのか気になってしまった。
だって調べたら65,535まで指定って書いてある！
わざわざ255にする必要あるのかな・・・?
> VARCHAR カラム内の値は可変長の文字列です。 長さは 0 から 65,535 までの値で指定できます。 
> [公式ドキュメントより](https://dev.mysql.com/doc/refman/8.0/ja/char.html)

### そもそも指定できるって何？文字数を？バイト数を？
> VARCHAR カラム内の値は可変長の文字列です。 長さは 0 から 65,535 までの値で指定できます。 VARCHAR カラムの有効な最大長は、最大行サイズ (65,535 バイト、すべてのカラムで共有される) と使用される文字セットによって決まります。
> [公式ドキュメントより](https://dev.mysql.com/doc/refman/8.0/ja/char.html)

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

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

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

例えば latin1 という１文字が１バイトの文字コードがあります。
この場合、
```math
655,35バイト\div1文字1バイト=65,535文字
```
なので65,535文字まで入ります。

しかし、utf8mb4では文字によって1~4バイトになります。
仮に全ての文字が4バイトと仮定すると、
```math
655,35バイト\div1文字4バイト=16,383文字
```
で16,383文字まで入ります。


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


### 255文字を指定する理由は？
まず、VARCHARは可変長の文字列型であるという点が重要です。
> VARCHAR カラム内の値は可変長の文字列です。
> [公式ドキュメントより](https://dev.mysql.com/doc/refman/8.0/ja/char.html#:~:text=VARCHAR%20%E3%82%AB%E3%83%A9%E3%83%A0%E5%86%85%E3%81%AE%E5%80%A4%E3%81%AF%E5%8F%AF%E5%A4%89%E9%95%B7%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97%E3%81%A7%E3%81%99%E3%80%82)

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

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

可変長の文字列型は、データの先頭に、値のバイト数を表すみたいです。
> 1 バイトまたは 2 バイト長のプリフィクスの付いたデータとして格納されます。
> [公式ドキュメントより](https://dev.mysql.com/doc/refman/8.0/ja/char.html#:~:text=1%20%E3%83%90%E3%82%A4%E3%83%88%E3%81%BE%E3%81%9F%E3%81%AF%202%20%E3%83%90%E3%82%A4%E3%83%88%E9%95%B7%E3%81%AE%E3%83%97%E3%83%AA%E3%83%95%E3%82%A3%E3%82%AF%E3%82%B9%E3%81%AE%E4%BB%98%E3%81%84%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%81%A8%E3%81%97%E3%81%A6%E6%A0%BC%E7%B4%8D%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1544861/0b8d4511-89ee-bd50-d9d1-e3dda23e0f6f.png)


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

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

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

### でも1文字が１ビットならね！
`VARCHAR(255)`を指定し、255文字まで入るようにします。

例えばlatin1 という１文字が１バイトの文字コードなら、
```math
255文字\times1文字あたり1バイト=255バイト
```
になり、プリフィクスを１バイトに抑えることができます。

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

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

### プリフィクスの区切りはどこが良いか？
以上のようにプリフィクスが１バイトか２バイトになる区切りは、１文字あたりのバイト数によって変動します。

例えばもし全て1文字4バイトであるならば、
```math
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文字の指定は、必ずしもプリフィックスを減らせるわけではない。