こんにちは!データベースの世界へようこそ。
普段、仕事や趣味でアプリを作っていると、「あれ、なんか最近データが増えてきて、動きが重いな?」と感じること、ありますよね。そんなとき、多くのエンジニアが最初に頼るのが「インデックス(索引)」です。
今日は、PostgreSQLで「もっと速く、もっとスマートに」データを検索するための、ちょっと気の利いたテクニック「カバリングインデックスとINCLUDE句」についてお話しします。
—
本棚と「メモ書き」の不思議な関係
データベースのインデックスを、図書館の「図書カード」や本の「索引」に例えることはよくありますよね。でも、今日はもう少し身近な例で考えてみましょう。
あなたが、山のような書類が整理されたオフィスで、「特定の人の電話番号」を探していると想像してください。
普通なら、「名前のリスト(インデックス)」を見て、その人の席番号を見つけ、その席まで行って電話帳を開きますよね。これ、データベースの世界では「インデックスを使って場所を特定し、元のテーブルを見に行く」という、ちょっと二度手間な動きなんです。
でも、もしその「名前のリスト」に、「電話番号も一緒にメモされていたら」どうでしょう?
わざわざ席まで行く必要はありませんよね。リストを見ただけで用事が済んでしまいます。これが、今回紹介する「インデックスオンリースキャン」の考え方です。
—
普通のインデックスの限界と「INCLUDE句」の救済
PostgreSQLでインデックスを作るとき、普通は検索条件(WHERE句)に使うカラムを指定しますよね。でも、検索結果として「電話番号も一緒に欲しい」となったとき、PostgreSQLはわざわざ元のテーブルまでデータを取りに行こうとします。
ここで登場するのが、PostgreSQLの強力な助っ人「INCLUDE句」です。
これは、インデックスの中に「検索には使わないけど、結果として表示したいデータ」をこっそり含めておくための魔法のフレーズなんです。
どうやって書くの?
例えば、`users` テーブルから `email` を使って `phone_number` を探したいとき、こんな風にインデックスを作ります。
CREATE INDEX idx_users_email_include_phone
ON users (email)
INCLUDE (phone_number);
たったこれだけ。「`email` で検索するよ。でも、ついでに `phone_number` もインデックスの中に抱え込んでおいてね!」とデータベースに伝えているんです。
—
この方法を使うと、何が嬉しいの?
最大のメリットは、「ディスクへのアクセス回数が劇的に減る」こと。
ハードディスクやSSDって、CPUに比べると実はすごく動きが鈍いんです。だから、データベースが「あ、必要なデータ全部インデックスにあるじゃん!元のテーブルまでわざわざ見に行かなくていいや」と気づいてくれた瞬間、クエリは爆速になります。
これが、いわゆる「インデックスオンリースキャン」という状態ですね。
注意点も忘れずに
「じゃあ、全部の列をINCLUDEに入れちゃえばいいじゃん!」と思いますよね。でも、ちょっと待ってください。
- インデックスが肥大化する: インデックスも容量を食います。全部入れてしまうと、逆にインデックスが重くなって管理が大変になります。
- 更新時のコスト: データが書き換わるとき、インデックスも一緒に書き換える必要があります。詰め込みすぎると、データの追加や更新が少しずつ遅くなってしまいます。
「よく検索するけど、変更はあまりされないデータ」をピンポイントで含めるのが、賢いエンジニアの腕の見せ所です。
—
最後に:データベースとの対話を楽しもう
クエリチューニングは、パズルに似ています。「どこにインデックスを貼れば、データベースが一番楽に動けるかな?」と考えるのは、まるでデータベースと対話しているような感覚で、意外と楽しいものですよ。
今日紹介した `INCLUDE` 句、ぜひあなたのプロジェクトでも試してみてください。きっと、画面の向こう側のデータベースが、今までより少し軽やかに動いてくれるはずです。
もし「うまくいったよ!」なんて報告があったら、ぜひコメントで教えてくださいね。それでは、また次回の記事でお会いしましょう!
コメント