長大な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 の結合が多いからだろうけど。