なぜ、PostgreSQLはたまに「とんでもない遠回り」をするのか?
こんにちは!データベースの世界にどっぷり浸かって十数年、今日も今日とてSQLのチューニングに明け暮れているエンジニアです。
皆さんは、PostgreSQLを使っていて「あれ、このクエリ、インデックスを貼ったはずなのに全然速くならないぞ?」と首をかしげたことはありませんか? まるで、最短ルートを知っているはずのタクシー運転手が、わざわざ大渋滞の裏道を選んでしまったような……そんなもどかしさ。
実はこれ、データベースの「頭脳」であるプランナ(実行計画作成者)が、ちょっとした「勘違い」をしているのが原因かもしれません。今回は、そんなPostgreSQLの頭の中を覗いてみましょう。
—
「目次」がない図書館で本を探す苦労
まず、想像してみてください。あなたは巨大な図書館の司書です。本は100万冊あるけれど、どこに何があるか書かれた「目次(インデックス)」が、実はめちゃくちゃ古いまま放置されていたらどうなるでしょうか?
「たぶん、この棚には歴史の本が多いはずだ」という古い記憶を頼りに探しても、実際に行ってみたらそこには料理本しかなかった……なんてことが起きますよね。
PostgreSQLも同じです。「テーブルの中にどんなデータが、どれくらいの割合で入っているか」という情報を、独自のメモ帳に書き留めています。これが「統計情報」と呼ばれるものです。
ANALYZEは「最新の棚卸し」
PostgreSQLは、テーブルのデータがどんどん増えたり消えたりすると、次第にそのメモ帳の内容と実態がズレてきます。すると、プランナは「インデックスを使うより、全部の棚を順番に見たほうが速いかも?」なんて、とんでもない判断を下し始めるんです。
ここで登場するのが `ANALYZE` コマンド。これは、図書館でいうところの「定期的な棚卸し」です。
ANALYZE テーブル名;
これを実行すると、PostgreSQLは「今、この棚にはどんな本がどれくらいあるか」を再確認して、メモ帳を最新の状態に書き換えてくれます。これだけで、急にクエリが爆速になることは珍しくありません。「最近、なんだかデータベースが重いな」と思ったら、まずはこの棚卸しを疑ってみてください。
`pg_stats` を覗いて、プランナの目線を知る
「一体、PostgreSQLはどうやって判断しているの?」と気になったら、`pg_stats` という特別なビューを見てみましょう。これは、プランナが使っている「メモ帳の中身」そのものです。
例えば、ある列に「どんな値がよく出てくるか(頻度)」や「どれくらい値の種類があるか(カーディナリティ)」が記録されています。
- 値の種類が多い列: インデックスを使う価値が高い!(ピンポイントで探せる)
- 値の種類が少ない列(男女別など): インデックスを使っても半分くらいヒットしちゃうから、わざわざインデックスを通るより全部読んだ方が速いかも。
プランナは、この統計情報を元に「コスト(労力)」を計算しています。「インデックスをたどる手間」と「テーブルを全部読み込む手間」、このどちらが少ないかを天秤にかけているんですね。
まとめ:プランナを信頼しつつ、導いてあげる
プランナは非常に優秀ですが、あくまで「統計情報というデータ」に基づいて判断しています。だからこそ、私たちエンジニアの仕事は、「最新の正しい情報をプランナに与えてあげること」なんです。
1. こまめな ANALYZE: データの変化を正しく伝える。
2. 統計情報の確認: `pg_stats` で、偏ったデータになっていないか確認する。
3. 無理強いをしない: どうしても遅い場合は、統計情報の精度を上げる(統計対象の粒度を調整する)といったテクニックもあります。
データベースとの付き合いは、まるで相棒とのコミュニケーションです。たまに機嫌を損ねることもあるけれど、仕組みを知って少しだけケアをしてあげれば、きっと素晴らしいパフォーマンスで応えてくれますよ。
皆さんのデータベースライフが、今日も快適なものになりますように!また次回の記事でお会いしましょう。
コメント