web-dev-qa-db-ja.com

Postgres 11からPostgres 12へのアップグレードは、おそらく新しいCTE処理が原因で、いくつかのクエリを300倍遅くしました

私のアプリケーションは現在PostgreSQL 11.6を使用しています。今日、仮想マシンでPostgreSQL 12.1をテストしましたが、結果は衝撃的でした。バージョン11(同じVM)で100ミリ秒かかる重要なクエリの1つで、Postgres 12では約36秒かかります。これは300倍以上遅くなります。

私の疑いは、CTEの新しい処理、つまりMATERIALIZEDNOT 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の方が優れていると言われています)。

編集:結果を比較可能にするためにチェックした内容:

  • 同じ仮想マシン
  • 同じで非常に小さいデータセット
  • 同じpostgresql.conf
  • 再インデックス
  • vacuum analyze

EXPLAIN ANALYZEの結果: Postgres 11Postgres 12

3
cis

他のより具体的な質問への回答 で指摘されているように、理由はジャストインタイムコンパイルです。

SET jit = false;私の場合、すべてのパフォーマンスの問題を解決します。

2
cis