「なんでそんなに遅いの?」を解決する!PostgreSQLの隠し味『拡張統計情報』のお話
こんにちは!データベースの世界へようこそ。
日々PostgreSQLと向き合っていると、たまに「どうしてデータベース君は、そんなに効率の悪いルートを選んじゃうの?」と頭を抱えたくなるようなクエリに出会うこと、ありませんか?
「ちゃんとインデックスも貼っているし、条件も間違っていないはずなのに、なぜか検索が遅い……」
実はそれ、データベースが「勘違い」をしているのが原因かもしれません。今日は、そんなデータベースの勘違いを直して、クエリを爆速にするための魔法のスパイス『拡張統計情報(CREATE STATISTICS)』についてお話しします。
—
データベースは「優秀だけど、ちょっと天然」
データベースがクエリを実行するとき、必ず「どうやってデータを探せば一番早いかな?」という計画(実行計画)を立てます。でも、この計画を立てるとき、データベースは「統計情報」という、いわば「データの健康診断結果」のようなものを見ているんです。
ところが、この健康診断にはちょっとした弱点があります。それは、「列ごとの統計は詳しく見ているけれど、列同士の繋がりまでは見ていない」ということ。
これだと、ちょっと困ったことが起きます。例えば、こんなケースを想像してみてください。
- テーブル: お洋服の在庫管理
- 列A: 「ブランド名」
- 列B: 「サイズ」
もしあなたが、「ユニクロ」かつ「XXLサイズ」の商品を探そうとしたとき、データベースはこう考えます。
「ユニクロの服はたくさんあるな(列Aの統計)。XXLサイズの服も世の中にはそこそこあるな(列Bの統計)。よし、この2つの条件を掛け合わせると、対象はこれくらいかな……?」
でも実際には、そのブランドは「小さいサイズしか作っていない」かもしれないですよね。列同士に深い関係がある場合、データベースの「別々に計算して掛け合わせる」という手法は、大きく的外れな結果を生んでしまうんです。
『拡張統計情報』は、二人の仲の良さを教えること
この「勘違い」を直すのが、`CREATE STATISTICS` です。
これは簡単に言うと、データベースに対して「この列とこの列は、こういう関係性があるんだよ!」と教えてあげることです。
例えるなら、仕事のチーム編成のようなもの。
「AさんとBさんは、いつもセットで行動するから、別々に予定を組むんじゃなくて、ペアとして考えてね」とマネージャー(データベース)に伝えてあげるんです。
そうすると、データベースは「おっと、そうだったのか!それならもっと効率的な近道があるね」と、今までとは全く違う、賢いルートを選択してくれるようになります。
どうやって使うの?
使い方は驚くほどシンプルです。例えば、`users` テーブルの `city`(都市)と `zip_code`(郵便番号)の間に強い相関があるなら、こんなふうにコマンドを打つだけです。
CREATE STATISTICS stats_city_zip ON city, zip_code FROM users;
これだけで、PostgreSQLは「あ、この2つの列はセットで見るといいのね」と学習してくれます。あとは、`ANALYZE` コマンドで統計情報を更新してあげるのを忘れずに。
最後に:魔法の使いすぎには注意!
ここまで読んで「じゃあ、全部の列に設定しちゃえ!」と思ったあなた、ちょっと待ってくださいね。
この機能は便利ですが、あまりにたくさん作りすぎると、今度は「統計情報を計算する作業」そのものがデータベースの負担になってしまいます。また、単純なテーブルや、全く関係のない列同士に設定しても意味がありません。
- 「複数条件で絞り込むことが多いのに、なぜか実行計画が変だ」
- 「特定の列同士の組み合わせが、結果の件数に大きく影響している」
そんな「ここぞ!」という場所にピンポイントで使ってあげるのが、一番の近道です。
データベースのチューニングは、まるで料理の味付けのようなもの。隠し味を上手に使って、あなたのクエリを最高のパフォーマンスに仕上げてみてくださいね。
それでは、また次回の記事でお会いしましょう!Happy Coding!
コメント