MySQL道普請便り

第44回 MySQLで扱える文字列型の種類を理解する

この記事を読むのに必要な時間:およそ 4.5 分

第41回では,CHAR型とVARCHAR型の違いについて簡単に説明を行いました。しかし,MySQLにはそれ以外にも文字列を扱うことができる型が複数あります。そこで今回はMySQLで扱える文字列型について紹介していきます。

検証環境

今回使用した環境は,CentOS7.1上にyumコマンドを利用してインストールしたMySQLの5.7.18上で動作検証を行っています。第41回と同様に,今回使う検証用のデータベースを作成しました。

mysql> CREATE DATABASE characters;
Query OK, 1 row affected (0.00 sec)
mysql> use characters
Database changed

MySQLの文字列型

MySQLには大きく分けて,文字列を扱える以下の8つの型が存在しています。

  • CHAR
  • VARCHAR
  • BINARY
  • VARBINARY
  • BLOB
  • TEXT
  • ENUM
  • SET

続いて各型の紹介をしていきます。CHAR型,VARCHAR型に関しては以前紹介させていただいたので割愛させていただきます。

BINARY型とVARBINARY型

BINARY型とVARBINARY型の関係はCHAR型とVARCHAR型の関係と非常によく似ています。BINARY型はデータを固定長で扱い,VARBINARY型はデータを可変長で扱います。そのためBINARY型ではパディングの処理に関してもCHAR型同様に注意する必要があります。

同様に確認してみましょう。まずは固定長のBINARYから確認します。以下のように長さが4のBINARY型のテーブルを用意します。続けて確認用に末尾にスペースがないa bと末尾にスペースがあるa bをINSERTします。

mysql> CREATE TABLE bin(bin BINARY(4));
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO bin(bin) VALUES ('a b ');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO bin(bin) VALUES ('a b');
Query OK, 1 row affected (0.00 sec)

どのように格納されているか,CONCAT構文を利用して確認してみましょう。

mysql> select CONCAT('(',bin,')') from bin;
+---------------------+
| CONCAT('(',bin,')') |
+---------------------+
| (a b )              |
| (a b )              |
+---------------------+
2 rows in set (0.00 sec)

CHAR型の時とは逆に,末尾にスペース(本当は0x00)が追加されていることが確認できます。

続けてVARBINARY型を見てみましょう。同様に型を作成し,以下のINSERT文をを実行しました。

mysql> CREATE TABLE varbin(bin VARBINARY(4));
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO varbin(bin) VALUES ('a b');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO varbin(bin) VALUES ('a b ');
Query OK, 1 row affected (0.00 sec)

それではどのように格納されているか確認してみましょう。

mysql> select CONCAT('(',bin,')') from varbin;
+---------------------+
| CONCAT('(',bin,')') |
+---------------------+
| (a b)               |
| (a b )              |
+---------------------+
2 rows in set (0.00 sec)

こちらはVARCHAR型の時と同様に長さに合わせた値として保存されていることがわかります。

それ以外のCHAR型とVARCHAR型との違いとしては,文字列を認識して保存するのではなく,文字列をバイト文字列として保存します。そのため文字セットの影響を受けず,ORDER BY構文などを用いて並べ替えを行う際には,文字列の順序として並べ替えをするのではなく,バイトの文字列,つまり数字としてとしての比較を行い並べ替えます。条件句で指定をする際に,アルファベットの大文字と小文字が区別されることにも注意が必要です。他にも不正な文字列かどうかのバリデーションがチェックされません。そのためマルチバイト文字に関しては,これらの型を使用するのはやめておいたほうが良いでしょう。

BLOB型とTEXT型

BLOB(Binary Large OBjectの略)型とTEXT型は,VARBINARY型やVARCHAR型で扱うことができなかった大きなサイズのファイルや文字列を扱うために利用します。

BLOB型はTINYBLOB, BLOB, MEDIUMBLOB, LONGBLOBの4種類が存在します。またTEXT型でも同様にTINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT型の4種類が存在します。これらの違いは保存できるデータの最大長です。各型での最大長は以下の表の通りになります。

型名最大長
TINYBLOB, TINYTEXT255バイト
BLOB, TEXT65,535バイト
MEDIUMBLOB, MEDIUMTEXT16,777,255バイト
LONGBLOB, LONGTEXT4,294,967,295バイト

BLOB型とTEXT型は,BLOB型はVARBINARY型に,TEXT型はVARCHAR型にそれぞれ非常に良く似ています。しかし,保存できるデータが大きいため,インデックスを貼る際には最初の何文字・何バイトまでを対象とするかを考慮して使う必要があります。TEXT型を例に確認してみましょう。以下のようにテーブルを作成します。

mysql> CREATE TABLE text(text TEXT);
Query OK, 0 rows affected (0.01 sec)

続けて,textテーブルのtextカラムにインデックスをそのまま貼ってみるとどうなるか確認してみましょう。

mysql> ALTER TABLE text ADD INDEX index_text(text);
ERROR 1170 (42000): BLOB/TEXT column 'text' used in key specification without a key length

BLOB/TEXTのカラムは長さを指定しましょうというエラーが発生しています。次は長さに制約を付けてみましょう。以下では10文字という制限を付けてみました。カラム名の後ろの()でくくられた部分が長さを示しています。

mysql> ALTER TABLE text ADD INDEX index_text(text(10));
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

無事作成できました。このように,TEXT型やBLOB型のカラムに対してインデックスを張りたい場合は長さに注意が必要です。また,特にTEXT型のカラムにマルチバイト文字を使用した場合は,その分長さが減ることにも注意しましょう。

一般的にこれらの型を使用する際には,保管するデータは非常に大きなものが入っていることが多いです。そのためアクセスする際には必要に応じて,たとえばこれらの型を含むテーブルからSELECTする時に,なるべくこの型を使ったカラムを入れないようにしたほうが良いでしょう。大きなデータを扱う時には,加えてmax_allowed_packetinnodb_log_file_sizeを十分に大きくしないとエラーが発生してしまうこともあるので注意してください。

BLOB型に画像や動画などの大きなファイルを入れたい場合は,別途MySQL以外のストレージも検討したほうが良いかもしれません。

著者プロフィール

木村浩一郎(きむらこういちろう)

GMOメディア株式会社 技術推進室所属のWebアプリケーションエンジニア。最近はミドルウェア・インフラ周りのことも少しずつ学習しています。趣味は将棋。好きな戦法は四間飛車。

Twitter:@kk2170

コメント

コメントの記入