私のアプリケーションは現在PostgreSQL 11.6を使用しています。今日、仮想マシンでPostgreSQL 12.1をテストしましたが、結果は衝撃的でした。バージョン11(同じVM)で100ミリ秒かかる重要なクエリの1つで、Postgres 12では約36秒かかります。これは300倍以上遅くなります。
私の疑いは、CTEの新しい処理、つまりMATERIALIZED
、NOT MATERIALIZED
がその原因であるということです。
すべてのCTEをMATERIALIZED
に変更すると、クエリが36秒から6秒に下がります。大幅に改善されましたが、バージョン11よりも50倍以上遅くなっています。
私がそれを正しければ、PostgreSQL 12では2つの代替オプションがあります:
MATERIALIZED
を使用すると、CTEは1回だけ実行されますが、インデックスの利点を失うNOT MATERIALIZED
を使用すると、インデックスのメリットが得られますが、CTEは結果にアクセスするたびに実行されます。あれは正しいですか?
トリックはありますか? Postgres 11の動作に戻るための特別な設定?または、MATERIALIZED
またはNOT MATERIALIZED
の方が優れている場合、これを手動で評価してすべてのCTEを評価する唯一の方法ですか?
かなり頻繁に、私は推測する、どちらの方法がより良いのかはっきりしない。私のアプリケーションには数百のCTEが含まれており、その多くはテーブルクエリと負荷の高い関数呼び出しの両方を実行します( docs の例では、NOT MATERIALIZED
の方が優れていると言われています)。
編集:結果を比較可能にするためにチェックした内容:
vacuum analyze
EXPLAIN ANALYZE
の結果: Postgres 11Postgres 12
他のより具体的な質問への回答 で指摘されているように、理由はジャストインタイムコンパイルです。
SET jit = false;
私の場合、すべてのパフォーマンスの問題を解決します。