【入門編】 GINインデックス – PostgreSQL

こんにちは!データベースの世界へようこそ。

普段、PostgreSQLを使っていると「検索を速くしたいな」という場面に必ず出くわしますよね。そんなとき、真っ先に思い浮かぶのが「インデックス(索引)」です。

でも、普通のインデックス(B-treeといいます)は、名前やIDのような「一つの値」を探すのは得意だけど、「たくさんの要素が詰まったデータ」の中身を探すのはちょっと苦手なんです。

今日は、そんな苦手分野をさらりと解決してくれる、ちょっと頼れる相棒「GIN(ジン)インデックス」について、日常の例えを交えてお話ししますね。

—

本の「索引」と「巻末のキーワードリスト」の違い

まず、想像してみてください。

皆さんが持っている分厚い専門書を。後ろの方にある「索引」をイメージしましょう。
「PostgreSQL」という単語を調べたいとき、索引を見れば何ページに書いてあるか一発でわかりますよね? これが普通のインデックスの動きです。

では、もし皆さんが「料理のレシピ本」を作っているとしたらどうでしょう?
「冷蔵庫に卵とトマトしかない!この2つを使ったレシピを教えて!」と言われたとき、普通の索引だと「卵」のページをめくり、「トマト」のページをめくり……と、すごく時間がかかってしまいますよね。

ここで登場するのが「転置インデックス(GINの正体)」です。

これは、本の後ろにこう書いてあるようなものです。

  • 卵: 10ページ、15ページ、22ページ
  • トマト: 10ページ、12ページ、22ページ

これなら、「卵」と「トマト」の両方が載っているページ(10と22!)を、本の中身を全部見ることなく一瞬で見つけ出せますよね。これがGINインデックスの魔法なんです。

GINインデックスが輝く場面

PostgreSQLでいうと、GINインデックスは主にこんなデータ型で大活躍します。

  • 配列型: `[‘りんご’, ‘バナナ’, ‘みかん’]` みたいに複数の値が入っているもの
  • JSONB型: 最近流行りの、いろんなデータが詰め込まれた箱のような形式

例えば、ユーザーの「趣味」を配列で持っているテーブルを想像してみてください。
「『キャンプ』と『読書』の両方が趣味の人を抽出したい!」という検索をするとき、GINインデックスが張ってあれば、データベースは迷わず該当するユーザーをリストアップしてくれます。

これがないと、データベースは全ユーザーの趣味を一人ずつ確認していくという、気の遠くなるような作業(フルスキャン)をしなければならないんです。

「便利だけど、ちょっとだけ気難しい」一面も

ここまで聞くと「じゃあ全部GINにしちゃえばいいじゃん!」と思うかもしれませんが、実はちょっとしたトレードオフがあるんです。

GINインデックスは「作るのに時間がかかる」という特徴があります。
先ほどの料理本の例でいうと、全ての食材をリストアップして、どのページに何があるか紐付ける作業……すごく大変そうですよね?

  • 書き込みが少し遅くなる: 新しいレシピを追加するたびに、この複雑なリストを更新しないといけないからです。
  • サイズが大きくなる: 情報を細かく分解して保存するので、インデックス自体のサイズもそれなりに大きくなります。

つまり、「頻繁に更新されるデータ」よりも「一度作ったらあまり変わらない、読み取り重視のデータ」に使うのが、GINと仲良くするコツなんです。

—

まとめ:適材適所で使いこなそう

最後に今日のまとめです。

  • GINは「中身の要素」で検索したいときの切り札!
  • JSONBや配列といった、リッチなデータ型と相性抜群。
  • ただし、インデックスを作るのには労力が必要なので、ここぞという場所に張ってあげよう。

データベースのチューニングって、まさに料理と同じで「どの道具を、どのタイミングで使うか」というセンスが問われる面白い作業です。

もし今、皆さんのテーブルで「JSONデータの中身がなかなか検索できなくて重いんだよね……」と悩んでいるなら、ぜひ一度GINインデックスを試してみてください。きっと、そのスピードの変化に驚くはずですよ!

それでは、また次回の記事でお会いしましょう!Happy Coding!

コメント

タイトルとURLをコピーしました