【MySQL】CHAR型とVARCHAR型の違い、使い分け
まえがき
MySQLにおいてCHAR型とVARCHAR型はどちらとも文字を格納できる型ですが、具体的な内部の動作を知りたいなと思い、CHAR型とVARCHAR型について調べてみました。
結論から申し上げると、データの長さが一定のものはCHAR型、不定なものはVARCHAR型が適していると思います。
CHAR型
CHAR型は必ず指定した長さ (固定長) の領域を使います。
例えばあるカラムをCHAR(5)と定義すると、そのカラムに格納される文字が1文字 (例: H) であっても5文字 (例: Hello) であっても、どちらとも同じ長さの領域 (5バイト分) が確保されます。
1文字だけ格納した場合では、末尾の文字 (残りの4文字) が自動的にスペースで埋められます。
ただし、デフォルト設定だとデータを取り出す際には末尾のスペースが無視されます。
また、"H "のように末尾にスペースをつけて格納した場合においても"H"だけが取り出されます。
CHARの最大サイズは255です。
VARCHAR型
VARCHAR型は格納されるデータの長さ (可変長) だけの領域を使います。
例えばあるカラムをVARCHAR(5)と定義すると、そのカラムに格納される文字が1文字であった場合1文字分だけの領域しか使いません。
ですので、CHAR型で1文字だけ格納しようとした場合では末尾にスペースが自動的に埋められて5バイトとして領域が確保されましたが、VARCHAR型だと自動でスペースが埋められることがなく、1バイトとしてデータが格納されます。
VARCHAR型は末尾にスペースをつけて格納した場合、そのスペースも含んだデータが取り出されます。
CHAR型だと"H "のケースでは"H"が取り出されましたが、VARCHAR型と"H "が取り出されます。
VARCHARの最大サイズは65535です。
CREATE TABLE IF NOT EXISTS test (
test_varchar VARCHAR(5),
test_char CHAR(5)
);
INSERT INTO test (test_varchar, test_char)
VALUES('H ', 'H ');
SELECT test_varchar, CHAR_LENGTH(test_varchar), test_char, CHAR_LENGTH(test_char) FROM test;
CHAR型とVARCHAR型の比較
以上からVARCHAR型の方が使う領域が少なく、CHAR型の必要性がないのではと思うかもしれませんが、そうとは限りません。
確かに領域だけで見ると分が悪いのですが、CHAR型はVARCHAR型と比較してパフォーマンスが高いという性質があります。
CHAR型は先述した通り、固定長であるためいちいち確保する領域サイズを計算する必要がありません。
しかし、VARCHAR型はデータの長さに応じて確保する領域が異なってきますので、毎度サイズを計算する必要があります。
以上より、理論上だとCHAR型はVARCHAR型より高速です。
ただ、実際にはそこまで速度が変わらなかったです。
CREATE TABLE test_varchar_table (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
);
CREATE TABLE test_char_table (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
);
SELECT * FROM test_char_table LIMIT 200000; -- 0.058998
SELECT * FROM test_varchar_table LIMIT 200000; -- 0.066465
CHAR型とVARCHAR型の使い分け
CHAR型とVARCHAR型の解説をしましたので、それぞれの動きがわかってきたと思います。
では、どちらを使うべきでしょうか。
必ず長さが決まっているカラムに対してはCHAR型を使うべきだと思います。
例えば、従業員番号や銀行コード、郵便番号です。
銀行コードを例として挙げると、国内の銀行は4桁です。(ゆうちょ: 9900, 三井住友銀行: 0009)
将来変わることのない事象についてはCHAR型を用いていくべきだと思います。
基本的にCHAR型を定義するということは、データを格納する際に必ずその長さになるようなデータを格納するという設計になると思います。
よって、カラムの定義を見ただけで必ずデータが入ること、格納するデータの長さが固定であることが読み取れますので可読性が高まります。
また、そのように解釈できるので、データを新規登録する際にフロントエンドやバックエンドでバリデーション処理が容易にできます。
個人的には、ここの可読性が向上するところが一番のメリットじゃないかと思います。
一方で、ある程度の長さはわかるが場面によって長さが異なるというケースだとVARCHAR型が最適でしょう。
名前や住所だと固定長ではありませんが、ある程度の長さが想定できますのでVARCHAR型を使うべきでしょう。
サイズを決めるのは難しいですが、そのあたりはプロジェクトの要件によって異なると思います。
結論
データの長さが一定のものはCHAR型、不定なものはVARCHAR型を使う。
Discussion