こんにちは!データベースの世界へようこそ。
普段、本や資料を探すとき、みなさんはどうしていますか?もし図書館の蔵書がすべてバラバラに積み上げられていたら、目当ての一冊を見つけるのに何時間もかかってしまいますよね。
データベースにおける「インデックス(索引)」は、まさに図書館の目録のようなものです。これがあるおかげで、私たちは一瞬で目的のデータにたどり着けるわけです。
でも、たまに「普通の方法では検索がうまくいかない」という厄介なケースに遭遇します。今日はそんな悩みをスッキリ解決してくれる、PostgreSQLの「関数インデックス」という裏技についてお話ししますね。
—
普通のインデックスが「お手上げ」になる瞬間
例えば、ユーザーのメールアドレスを保存しているテーブルがあるとします。会員登録画面で「メールアドレスを入力してください」と案内しても、ユーザーさんは「Example@Gmail.com」と書いたり「example@gmail.com」と書いたりと、大文字と小文字を混ぜて入力することがありますよね。
システム側で「このユーザーは登録済みかな?」と探すとき、こんなクエリを書くことがよくあります。
SELECT FROM users WHERE LOWER(email) = ‘example@gmail.com’;
`LOWER()` という関数は、すべてのアルファベットを小文字に変換してくれる魔法のツールです。これを使えば、大文字・小文字の区別なく検索できます。
でも、ここで問題が。普通のインデックスは「そのままの値」を並べて整理整頓するものです。`LOWER(email)` という「変換後の値」まではインデックスの中に並んでいません。
結果として、データベースは「えっと、変換した後の値を知らないから、全部の行を端から順番にチェックするしかないな…」と、ものすごく時間がかかる作業(全件走査)を始めてしまうんです。これでは、ユーザーが増えるほどサイトが重くなってしまいますよね。
—
そこで登場!「関数インデックス」という切り札
こんなとき、「じゃあ、最初から『小文字に変換した状態』でインデックスを作っちゃえばいいんじゃない?」という天才的な発想が、関数インデックスです。
PostgreSQLでは、こんなふうに指示を出せます。
CREATE INDEX idx_users_lower_email ON users (LOWER(email));
こうすると、PostgreSQLは裏側で「メールアドレスを小文字に変換したリスト」を別途作って保持してくれます。
検索するときは、データベースはもう迷いません。「`LOWER(email)` のインデックスがあるね。じゃあ、そこに答えが書いてあるはずだ!」と、一瞬で目的の行を探し当ててくれるようになります。
—
日常で例えるとこんな感じ
これって、「辞書の索引」を「読み方(ひらがな)」で作り直すことに似ています。
もし、漢字の辞書を「画数順」だけで引くようになっていたら、読み方がわからない漢字を探すのは地獄ですよね。でも、「読み方順の索引」があれば、画数がわからなくても一発で引ける。関数インデックスは、まさに「目的に合わせた専用の索引」をもう一つ作るようなイメージなんです。
こんな場面でも大活躍します!
大文字・小文字の変換以外にも、こんなシーンで役立ちますよ。
- JSONの中身を検索する: 最近よく使うJSONB形式のデータで、「このJSONの中にある『order_id』というキーの値だけで検索したい!」というとき、その値に関数インデックスを張れば爆速になります。
- 日付の「年」だけ取り出す: 「2023年のデータだけ全部ほしい!」というとき、`EXTRACT(YEAR FROM created_at)` という式に関数インデックスを張れば、過去何年分あっても即座に抽出できます。
—
最後に:使いすぎには注意!
「便利だから全部インデックスにしちゃえ!」と思うかもしれませんが、ここでちょっとした注意点を。
インデックスは、新しくデータが増えるたびに「作り直し」のコストがかかります。関数インデックスをたくさん作りすぎると、データの追加や更新が少しだけ遅くなってしまうんです。
「よく検索するけど、なかなか見つからない!」という、まさにそのピンポイントな場所にだけ魔法をかけてあげる。これが、熟練エンジニアのスマートなやり方です。
ぜひ皆さんのプロジェクトでも、検索が遅い場所を見つけたら「あ、ここは関数インデックスが使えるかも?」と思い出してみてくださいね。
それでは、また次回の記事でお会いしましょう!Happy Coding!
コメント