データベースの「見積もり」が狂うとき:PostgreSQLのコスト定数って何?
こんにちは!日々の開発、お疲れ様です。データベースを触っていると、「あれ、このクエリなんでこんなに遅いの?」と頭を抱える瞬間ってありますよね。
PostgreSQLは非常に賢いデータベースなので、実行する前に「どうやってデータを取ってくるのが一番速いかな?」という計画(実行計画)を、自分自身で立ててくれます。
でも、たまにその計画が「空回り」してしまうことがあるんです。まるで、「近道があるのに、わざわざ遠回りをして渋滞に巻き込まれる」ような計画を立ててしまうこと、ありませんか?
今回は、その原因になりがちな「コスト定数」という設定について、専門用語を極力使わず、日常の出来事に例えてお話ししますね。
—
「近道」か「高速道路」か、どう判断してるの?
PostgreSQLが実行計画を立てる際、実は頭の中で「コスト」という点数をつけています。この点数が低い道を選ぶのが、プランナ(計画を立てる担当者)の役割です。
このとき、基準になるのが「データの読み込みにどれくらい時間がかかるか」という見積もりなのですが、ここで重要になるのが2つのパラメータです。
- seq_page_cost(順次読み込みのコスト)
- random_page_cost(ランダム読み込みのコスト)
これ、何かに似ていませんか?そう、「本棚から本を探すとき」の探し方です。
1. seq_page_cost:本棚を端から端まで眺める(1冊ずつ順番に)
本棚の左端から右端まで、背表紙を指でなぞりながら探していくイメージです。これは非常に効率的で、動きに無駄がありませんよね。ハードディスクやSSDも、データを順番に読み込むときはこれに近い動きをします。
2. random_page_cost:本棚のあちこちを飛び回る(目次を見て探す)
逆に、本をランダムに選んでパッと開くのは、あちこちの棚に移動しないといけないので大変です。物理的に腕を動かして、別の棚へ走って……と、移動の負担が大きくなりますよね。
—
なぜ「見積もり」が狂ってしまうのか?
PostgreSQLのデフォルト設定は、実は「昔のハードディスク(HDD)」を基準に作られています。
昔のHDDは、ヘッドを物理的に動かしてデータを読み取っていたので、「ランダムにアクセスするのは、順番に読むより何倍も時間がかかる(コストが高い)」という大前提がありました。
でも、今の時代は違いますよね?
皆さんの環境が高速なSSDになっているなら、ランダムアクセスも驚くほど速いはずです。なのに、PostgreSQLが「あ、ランダムアクセスは高いからやめとこう。順番に全部読もう(シーケンシャルスキャン)」と判断し続けていたら……。
「SSDを使っているのに、HDD時代の古い感覚で計画を立てている」というミスマッチが起きている状態なんです。これだと、本来なら速いクエリも、わざわざ遅い方法を選んでしまいますよね。
—
設定をいじるときに覚えておいてほしいこと
「じゃあ、random_page_costを下げればいいんだね!」とすぐに設定変更したくなるかもしれませんが、ちょっと待ってくださいね。
設定をいじるときは、以下の3つを心に留めておいてください。
- 「今のストレージはどれくらい速い?」を意識する
SSDなら、random_page_costをデフォルトの「4.0」から「1.1」くらいまで下げてみるのが一般的です。これだけで、劇的に実行計画が変わることもあります。
- 一度に変えすぎない
コスト定数はデータベース全体に影響します。一つのクエリを速くしようとして、他の大事なクエリの計画がおかしくなったら大変ですよね。少しずつ調整して、様子を見るのがコツです。
- 「今のままでいい」可能性も疑う
実は、最近のバージョンのPostgreSQLはかなり優秀です。無理に設定を変えなくても、統計情報(データの分布状況)をちゃんと更新してあげるだけで解決することも多いですよ。
—
まとめ:データベースと対話しよう
データベースのチューニングと聞くと難しく感じますが、要は「今の環境に合った基準で判断してね」と教えてあげることなんです。
「このデータベース、ちょっと慎重すぎない?」と感じたら、それは設定が今のハードウェアと噛み合っていないサインかもしれません。
まずは `EXPLAIN ANALYZE` を使って、PostgreSQLが「どこに時間がかかると思っているのか」を覗いてみてください。彼らの言い分を聞いてあげると、意外と素直に改善案を教えてくれるものですよ。
それでは、また次回の記事でお会いしましょう!皆さんのDB運用が、少しでも快適になりますように。
コメント