RDBMS に MySQL を採用したシステムで、VARCHAR の代わりに TEXT を頻用するプロジェクトがあった。そんなに昔の話ではない。つい最近作られたシステムだ。

VARCHAR も TEXT も可変長文字列を格納する型で、アプリケーションから見るとあまり違いがない。どちらも SQL で同じように扱える。しかし、こんな場合は VARCHAR を使うのが当然じゃないか。わざわざ TEXT を使う理由がない。そう思ったのだが、調べてみると意外に複雑な問題であった。

使う SQL はほとんど同じでも、VARCHAR と TEXT の MySQL 内部における扱いは、だいぶ異なる。InnoDB の場合は、長い VARCHAR は自動的に TEXT と同じように扱われる。MyISAM の場合、VARCHAR は行の中にインラインで保管されるが、TEXT は別オブジェクトとして格納される。従って、SELECT の出力に TEXT型カラムが含まれる場合、ルックアップが一段階増える。これによってパフォーマンスへの影響が出るとは言えないが、メモリ使用量は確実に増える。さらに、ソートしようとするテーブルに TEXT が含まれる場合、オンメモリソートで使われる MEMORYストレージエンジンが TEXT を扱えないため、テンポラリテーブルを使った、より遅いソートに切り替えられる。これで、VARCHAR に替えて積極的に TEXT を使う理由はないことがわかった。

唯一、大きなサイズになる可能性があるテキストを扱うときは、TEXT のほうがいい。パフォーマンス云々というより、データの意味として、ブログ記事やメールテキストなどのようにサイズ上限が設けにくいテキストの場合は TEXT のほうが適切だ。そのほか、アプリ側でサイズ上限があったとしても、VARCHAR(10000) にするくらいなら TEXT のほうがいい。なんとなく気分的に。このあたり、パフォーマンス上の理由を語れないのがつらい。

よく見かける VARCHAR(255) というスキーマは、昔のなごりだ。2005年にリリースされた 5.0.3 (Beta版扱い、正式版は 5.0.4) で VARCHAR は最大255文字から65,535文字へと拡張された。これよりも前に作られたスキーマでは、255文字を超えるテキストを格納するのために TEXT を使う必要があった。パフォーマンスを考えると、インラインで格納するなら 255文字(バイトではなく文字)あたりが適切だろうと、MyISAM 全盛期に設計者が考えた結果だったのかもしれない。

TEXT vs. VARCHAR http://www.pythian.com/news/7129/text-vs-varchar/

MySQL: TEXT vs. VARCHAR Performance http://nicj.net/2011/01/20/mysql-text-vs-varchar-performance http://news.ycombinator.com/item?id=2531800

VARCHAR vs. TEXT - some performance numbers http://forums.mysql.com/read.php?24,105964,105964#msg-105964

What are MyISAM formats in MySQL? http://www.mysqlfaqs.net/mysql-faqs/Table-Types-or-Storage-Engines/MyISAM-Engine/What-are-MyISAM-formats-in-MySQL