「勘」に頼らないデータベース:PostgreSQLの「ヒストグラム」で検索を爆速にする話
こんにちは!データベースエンジニアの現場からお届けします。
皆さんは、お店でレジの行列に並んでいるとき、「この列、何分くらいで自分の番が来るかな?」って予想したことありませんか?目の前に5人いたら「まあ5分くらいかな」と予想するし、逆に100人いたら「あ、これは30分はかかるな」と判断しますよね。
実は、PostgreSQLがSQLを実行するときも、これと全く同じことをしているんです。「この検索条件だと、だいたい何万件くらいのデータが見つかるかな?」と、実行する前にこっそり予想しているんですよ。
今日は、その予想の精度を大きく左右する「ヒストグラム」という仕組みについて、専門用語を抜きにしてお話ししますね。
—
そもそも、なぜ「予想」が必要なの?
PostgreSQLは非常に賢いデータベースですが、一度に何億件ものデータをスキャンするのは苦手です。だから、「どの道順でデータを探しに行くのが一番早いか」を事前に決める「クエリプランナ」という司令塔がいます。
もし、この司令塔の予想が外れてしまうと、どうなるでしょうか?
「たった10件のデータを探すだけだから、近道で行こう!」と決めたのに、実際には100万件もデータがあって、結局ものすごく時間がかかってしまう……。そんな悲劇が起こります。この予想の精度を支えているのが、今回紹介する「ヒストグラム」という地図なんです。
ヒストグラムって、結局なんなの?
例えるなら、「図書館の背表紙の分布図」のようなものです。
例えば、図書館にある本の「厚さ」で考えてみましょう。
- 「薄い本(1cm未満)」は全体の何%?
- 「普通の厚さ(1cm〜3cm)」は全体の何%?
- 「分厚い辞書クラス(3cm以上)」は全体の何%?
これを全部数えて完璧なリストを作るのは大変です。だからPostgreSQLは、データをざっくりと「等間隔のビン(箱)」に分けて、「この箱にはだいたいこれくらいのデータが入っているはず!」とメモを残しておきます。
これがヒストグラムです。
なぜ「等間隔」が大事なの?
もし、データが「0から100」まであるのに、「0〜90」の箱と「91〜100」の箱しかなかったら、細かい分布なんて分かりませんよね?PostgreSQLは、この「箱」を適切に分けることで、値が偏っている場所(例えば、特定の価格帯に商品が集中しているなど)をうまく把握しようとしているんです。
「検索が遅いな」と感じたら
もし皆さんが書いたSQLで、`BETWEEN`や`>`、`<`を使った範囲検索が極端に遅いと感じたら、この「ヒストグラム」が実態とズレている可能性を疑ってみてください。 例えば、
- 昨日、数百万件のデータを一気にインポートしたばかり。
- その後、一度も統計情報を更新していない。
こんな状態だと、PostgreSQLは「昔の古いヒストグラム」を頼りにしています。「昔はデータが少なかったから、今回もすぐ終わるだろう」という思い込みですね。これが「勘違い」の正体です。
そんなときは、PostgreSQLに「最新の状況をもう一度確認して!」と伝えてあげましょう。
ANALYZE テーブル名;
たったこれだけのコマンドですが、これだけでPostgreSQLは最新の「ヒストグラム」を書き直してくれます。司令塔が最新の地図を手に入れるので、迷わずに最短ルートを選べるようになるんです。
—
まとめ:データベースと仲良くなるために
データベースのチューニングと聞くと、難しそうな数式や設定ばかりを想像しがちです。でも、実際には今回紹介した「ヒストグラム」のように、「今のデータの状態を正しく教えてあげる」という、ちょっとしたコミュニケーションが一番大切だったりします。
PostgreSQLは、皆さんが正しく情報を与えてあげれば、必ず期待に応えてくれる相棒です。
「なぜこのSQLは遅いんだろう?」と悩んだら、ぜひ「今のデータの分布、ちゃんと伝わってるかな?」と、ヒストグラムのことを思い出してみてくださいね。
それでは、また次回のブログでお会いしましょう!Happy Querying!
コメント