「なぜかクエリが遅い」を解決する第一歩。PostgreSQLの `track_counts` を見直そう
現場で長くPostgreSQLを触っていると、若手から「昨日まで爆速だったクエリが、今日はなぜか重いんです」という相談を受けることがよくあります。
そんな時、僕が真っ先に確認するのが `track_counts` という設定です。
「統計情報? そんなのデフォルトでオンになってるでしょ?」と思うかもしれません。確かにその通り。でも、このパラメータが何をやっていて、もし無効になったらDBがどうなるのか。ここを深く理解しているかどうかで、トラブルシューティングのスピードが劇的に変わります。
今日は、クエリチューニングの「足元」を支えるこの機能について、少し掘り下げて話してみましょう。
—
track_counts とは何者か?
一言で言えば、`track_counts` は「DBの行動記録係」です。
PostgreSQLは、どのテーブルにどれだけアクセスがあったか、どのインデックスが使われたかといった統計情報をバックグラウンドで集計しています。この情報を元に、PostgreSQLのオプティマイザ(クエリプランナー)は「よし、今回はインデックスを使おう」とか「いや、フルスキャンの方が速いな」といった判断を下します。
`track_counts` を `on` にしておくと、PostgreSQLは以下の情報を収集し続けます。
- テーブルやインデックスの読み取り・書き込み回数
- 死んだタプル(不要になった行)の数
- 最後にバキュームやアナライズが行われた時刻
これがなければ、オプティマイザは「盲目」状態でクエリを投げることになります。結果として、本来なら数ミリ秒で終わるはずのクエリが、フルスキャンで何秒もかかる……なんて悲劇が生まれるわけです。
—
現場での確認方法:まずはここを見ろ
まずは、現在の設定を確認してみましょう。DBにログインして、以下のクエリを叩いてみてください。
SHOW track_counts;
もしこれが `off` になっていたら……即座に修正が必要です。`postgresql.conf` で `track_counts = on` に設定し、再読み込み(`pg_ctl reload`)をしてください。
さらに重要なのが、統計情報がちゃんと機能しているか確認することです。以下のビューを眺めてみてください。
— テーブルごとのアクセス統計を見る
SELECT relname, seq_scan, seq_tup_read, idx_scan
FROM pg_stat_user_tables;
もしここに表示される数字がいつまで経っても変わらないなら、統計コレクタが止まっているか、何らかの理由で情報が反映されていません。チューニングを語る以前の問題です。
—
なぜこれが「チューニングの基礎」なのか
僕が新人によく言うのは、「統計情報が嘘をつくと、オプティマイザは必ずミスをする」ということです。
例えば、大量のデータを削除した直後に `ANALYZE` を実行しないと、PostgreSQLは「まだテーブルには100万行あるはずだ」と思い込みます。本来ならインデックスを使って数行だけ取ればいいのに、全件スキャンして全データを読み込みに行く……。現場でよくある「実行計画の迷走」の典型例ですね。
`track_counts` が有効であれば、`autovacuum` が正常に働き、統計情報が適切に更新されます。つまり、「統計情報の鮮度」を保つための土台がこの `track_counts` なんです。
—
注意点:パフォーマンスへの影響
「じゃあ、この機能を常にONにしておくと重くならないの?」という疑問を持つ方もいるでしょう。
結論から言うと、現代のハードウェアであれば、パフォーマンスへの影響は誤差レベルです。統計情報は専用のプロセス(統計コレクタ)が非同期で処理してくれるので、通常のクエリ実行の足を引っ張ることはほとんどありません。
ただし、極端な高負荷環境で、かつ書き込みが毎秒数万件発生するような特殊なケースでは、統計ファイルの書き込みがボトルネックになる可能性がゼロではありません。ですが、そんな環境でも「オフにする」のではなく、まずはストレージのIO性能を疑うべきです。
—
先輩からのアドバイス
「クエリが遅い」と相談されたら、まずは `EXPLAIN ANALYZE` を実行するでしょう。そのとき、もし実行計画の中で `actual time` と `estimated rows` (推計行数)に大きな乖離があれば、それは間違いなく統計情報の問題です。
1. `track_counts` はオンになっているか?
2. `autovacuum` は正常に動いているか?
3. `ANALYZE` は適切なタイミングで行われているか?
この3段構えでチェックする癖をつけるだけで、DBエンジニアとしてのレベルが一段上がります。
DBは正直です。私たちが正しく「見てあげる」設定をしてあげれば、必ず期待通りのパフォーマンスで返してくれます。まずは自分の担当しているシステムの `track_counts` を確認するところから、今日の業務を始めてみませんか?
それでは、また現場で会いましょう!
コメント