【入門編】 N-Distinct統計 – PostgreSQL

こんにちは!データベースエンジニアとして日々PostgreSQLと格闘している私ですが、今日は少しマニアックだけど、知っていると「おっ、やるな」と思われる「N-Distinct(エヌ・ディスティンクト)」というお話をしてみたいと思います。

「統計」とか「見積もり」なんて聞くと、なんだか難しそうですよね。でも、実はこれ、私たちの日常生活にある「あるある」と同じなんです。

—

そもそも、PostgreSQLは何を見て判断しているの?

PostgreSQLがクエリ(命令文)を実行するとき、実は裏で「このやり方でいいかな?こっちのほうが速いかな?」と一生懸命シミュレーションしています。

そのとき、PostgreSQLが一番頼りにしているのが「統計情報」という名のメモ帳です。例えば、「このテーブルには全部で1万行あるよ」「『都道府県』という列には47種類の値があるよ」といったデータが書かれています。

これがあるおかげで、PostgreSQLは「あ、この条件ならサクッと検索できそうだな!」と判断できるわけです。

「組み合わせ」になると、急に迷子になる

さて、ここからが本題です。例えば、こんなデータがあると想像してみてください。

  • 都道府県(東京、大阪、福岡……など47種類)
  • 市区町村(たくさんありますね)

ここで、「東京都の世田谷区」という条件で検索をかけたとします。
PostgreSQLは、「都道府県」の統計と「市区町村」の統計を別々に見て、「まあ、このくらいの行数かな?」と見積もります。

でも、ここで問題が発生します。「都道府県」と「市区町村」という2つの情報を組み合わせたとき、PostgreSQLは少し混乱してしまうんです。

「東京都の世田谷区」は1つしかないけど、PostgreSQLは「東京都も世田谷区も、それぞれバラバラに値がたくさんあるから、掛け合わせたら結構な行数になるんじゃない?」と、とんでもなく多い数字を予想してしまうことがあるんです。

これが「見積もりのミス」です。見積もりが外れると、PostgreSQLは「よし、一番時間がかかる方法で検索しよう!」なんていう的外れな選択をしてしまい、クエリが激重になる……なんてことが起こります。

「N-Distinct」という解決策

そこで登場するのが「N-Distinct(複数列統計情報)」です。

これは簡単に言うと、PostgreSQLに対して「ねえ、都道府県と市区町村をセットで見ると、ユニークな組み合わせはこれくらいあるから覚えておいてね!」と教えてあげる機能です。

料理に例えるなら……。
「カレー」という単語と「ライス」という単語を別々に考えるのではなく、「カレーライス」というセットメニューとしてメニュー表に載せておくイメージです。これなら、「カレー」と「ライス」を別々に頼む人より、ずっと正確に行数が予想できますよね。

どうやって設定するの?

PostgreSQLでこれを設定するのは驚くほど簡単です。以下のコマンドを実行するだけ。

CREATE STATISTICS 統計名 (ndistinct) ON 都道府県, 市区町村 FROM テーブル名;

これだけで、PostgreSQLは「なるほど、この2つの列を組み合わせると、これくらいのユニークな組み合わせがあるんだな!」と学習してくれます。

あとは、いつものように `ANALYZE` コマンドを実行しておけば、統計情報が最新の状態に更新されます。これでもう、見積もりのせいでクエリが遅くなるという悲劇とはおさらばです!

—

まとめ:データベースと仲良くなるために

データベースは、私たちが思っているよりもずっと素直です。私たちが正しい情報(統計情報)を教えてあげれば、それだけ期待に応えて、最高のパフォーマンスで動いてくれます。

もし皆さんのシステムで「なぜか特定の検索だけめちゃくちゃ遅いんだよな……」という悩みがあれば、この「N-Distinct」を思い出してみてください。

「もしかして、列の組み合わせが上手く伝わっていないのかな?」と考えてみるだけで、チューニングの腕前はグッと上がります。ぜひ、次の開発で試してみてくださいね!

それでは、また次回のブログでお会いしましょう。ハッピー・クエリライフを!

コメント

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