「とりあえずTEXT型でいいや」を卒業しよう。PostgreSQLの文字型、本当の選び方
データベース設計の初期段階、テーブル定義をしていて「あ、ここは名前を入れるからVARCHARかな、でもTEXTでも動くよな……」と悩んだことはありませんか?
実務でコードを書いていると、つい「とりあえず全部TEXT型にしておけば後で困らないし、PostgreSQLならパフォーマンスも変わらないって聞いたし」という結論に至りがちです。
でも、ちょっと待ってください。その「なんとなく」の積み重ねが、将来的にデータの整合性を損なったり、意外なところでパフォーマンスの足を引っ張ったりする原因になることもあるんです。
今日は、PostgreSQLにおける `CHAR(n)`, `VARCHAR(n)`, `TEXT` の違いを、教科書にはあまり書かれていない「現場の感覚」でお話しします。
—
1. 結論:迷ったら「TEXT」でいい、ただし……
いきなり結論から言いますね。PostgreSQLにおいて、この3つの型に内部的なストレージ効率やパフォーマンスの差はほとんどありません。
多くのRDB(特に昔のOracleやSQL Serverなど)では、`CHAR`や`VARCHAR`のサイズ指定がストレージの確保に影響していましたが、PostgreSQLの `TEXT` 型は非常に優秀です。可変長データとして動的に処理されるため、今のモダンなPostgreSQL環境であれば、`TEXT` を使っておけばまず間違いはありません。
じゃあ、なんで `VARCHAR(n)` や `CHAR(n)` が存在するのか。それは「データベース側でのバリデーション」という役割が非常に大きいからです。
—
2. それぞれの特性を「現場の視点」で整理する
TEXT型:最強のデフォルト
特に制約がない限り、`TEXT` 一択です。
- メリット: 長さを気にしなくていい。将来的に桁数が増えても(アプリ側の仕様変更があっても)スキーマ変更が不要。
- 注意点: アプリ側でバリデーションを忘れると、とんでもない長さの文字列がデータベースに突っ込まれてしまうリスクがあります。
VARCHAR(n):賢いガードレール
「この項目は絶対に100文字を超えてはいけない」というビジネスロジックが明確な場合に使うべきです。
- 実用的な使い方: 例えば「ユーザー名(50文字)」や「メールアドレス(255文字)」など。
- メリット: データベースレベルで `value too long for type character varying(50)` とエラーを返してくれるため、アプリケーションのバグによるデータ汚染を防ぐ「保険」になります。
CHAR(n):化石のようで、実は「型」としての個性
固定長型です。指定した長さより短い場合は、後ろにスペースが詰められます。
- 正直な感想: 現代のWeb開発で `CHAR(n)` を使う場面は、ほとんどありません。唯一あるとすれば、郵便番号や国コード(ISOコード)のように、データ長が完全に固定されている場合に、「このデータは絶対にこの長さだ」という強い制約を明示するくらいでしょうか。
- 注意点: 末尾の空白がトリミングされるかされないかという挙動でハマることがあるので、理由がない限り避けるのが無難です。
—
3. インデックス設計で気をつけるべきこと
「TEXTだとインデックスが遅くなるんじゃないの?」と心配する声を聞くことがあります。
結論から言うと、インデックスの速度自体は文字列型に大きく依存しません。 ただし、`TEXT`型だからといって、巨大な文章をインデックスに突っ込むのはNGです。
— よくある悪い例
CREATE INDEX idx_user_bio ON users (bio); — bioが長文だとインデックスが肥大化して死ぬ
もし、長い文章を検索対象にしたい場合は、`pg_trgm`(trigram)拡張を使ったインデックスや、Full Text Search(全文検索)を検討すべきです。型云々の前に、「インデックスとして何を保持させるか」という設計思想が重要になります。
—
4. 先輩からの実践アドバイス
私が新しいテーブルを設計するときは、こんな基準で決めています。
1. 何も考えずに `TEXT` で作る。
2. ビジネスロジックで「絶対にこれ以上入ってはいけない」という要件があるなら `VARCHAR(n)` にする。
3. 桁数が完全に固定されている(例:郵便番号7桁)なら、あえて `CHAR(7)` を検討する。
「じゃあ、最初から厳密に全部VARCHAR(n)にしておいた方が安全じゃない?」と思うかもしれません。しかし、後から「ごめん、やっぱりこの項目は500文字必要だった!」となったとき、`ALTER TABLE` で列の型を変更するのは、データ量が多いテーブルだとロックの問題で冷や汗をかく作業になります。
「柔軟性を残すためにTEXTを使い、壊してはいけない部分だけアプリケーション層または制約で守る」
これが、PostgreSQLと長く付き合っていくための、最も健康的でストレスの少ない付き合い方だと思います。
—
いかがでしたか?「型なんてどれでもいいよ」と言われていた駆け出し時代を乗り越えて、今は「なぜその型を選ぶのか」を言語化できるエンジニアになりましょう。
もしDB設計で迷ったら、またいつでも聞きに来てくださいね。現場からは以上です!
コメント