Posted at

PostgreSQLの Planning Time のチューニング

長大なSQLを書いていると

explain analyze

-- ... 100行以上の SQL

-- ... 100行以上の実行プラン

Planning Time: 17.411 ms
Execution Time: 1.675 ms

という感じになって、Execution Time より Plannning Time を高速化する必要が出てきた。

PostgreSQLは実行プランをキャッシュできないらしい。

https://use-the-index-luke.com/ja/sql/explain-plan/postgres/concrete-planning

この重いSQLだけ実行するコネクションプーリング用サーバーを置けばプリペアドステートメントでキャッシュできそうだけど、それはちょっとやりすぎである。

素直にPlanning Timeを高速化することを試す。

と言っても検索しても特に情報もなく、あれこれ試行錯誤して

explain analyze

-- ...

Planning Time: 8.543 ms
Execution Time: 1.680 ms

倍の早さになった。

ちょっとしたサンプルコードは無し。そもそもPlanning Timeが1msを超えるようなSQLはめっちゃ長いので簡単なサンプルというのは作れなさそう。

何をしたかというと、joinの条件をシンプルにした。

usingで重複を消すために列を追加したり、条件は無いよりはあった方がいいよね的にjoinの結合条件を複数指定していたんだけど、プライマリキーやユニークキーから複数の結合条件を選択できるようなjoinはやらない方が良いっぽい。

例えばアカウントIDとemailが共にユニークで、ログインテーブルとアカウントテーブルの結合はどちらでも出来る場合、無いよりはプランナに選択を任せよう的にjoin条件に二つとも指定するとPlanning Timeが遅くなるようだ。(いや、これぐらいの小さい選択ならどちらでも変わらないかもしれない)

27個のテーブルを結合してNested Loop が13階層ほどになってるが、Execution Timeは速い。

rows=1 loops=1 の結合が多いからだろうけど。