.NETで作る!

.NETに関するあれこれ(C#、VB.NET)

CTE(With句) vs View in Postgres

CTEとは「Common Table Expressions」のこと。ざっくり言えば「With句」のこと。

PostgresでWith句を使用していると遅いケースがあったので、Temporary view 作って対応したほうがいいのだろうかと思い「CTE vs View」で情報収集。

そしたら、こちらのサイトにとても有益な情報が!すばらしい!

www.sraoss.co.jp

結論

Postgres12以降なら「パフォーマンスはCTE≒View」なので、再利用性が高いならView、それ以外ならCTEでいいと思います。 注意点もあるのでそこは詳細を見て判断ください。

なお、Postgres12は2019年10月にリリースされています。

要約

  • Postgres11以前は、DTE(With句)を使用すると必ずマテリアライズ(メモリ、ディスクにクエリ結果を保存する)が起きる。
  • Postgres12はオプティマイザが賢くなって、マテリアライズの要・不要を判定するようになった。

Postgres12なら勝手にパフォーマンスを改善してくれる!すばらしい!

マテリアライズ回避方法

どんな場合でもCTEを非マテリアライズ化するわけではありません。以下の条件をすべて満たしている必要があります。

1.同じCTEが2回以上使われていない

2.CTE中に非immutable関数が使われていない

(1)は、同じCTEを2回以上使うのであれば、マテリアライズしてそれを使い回したほうが良いだろう、というのが理由です(必ずしもそうとは言い切れないので、その場合は後述の方法でマテリアライズを避けることができます)。 非immutable関数を使用している場合は必ずマテリアライズされますが、同じCTEが2回以上使われている場合であれば、キーワードを付けることでマテリアライズを回避できます。

回避策も用意されている!すばらしい!

構文

公式サイト参照。(NOT MATERIALIZE キーワード)

www.postgresql.jp

Googleで「Postgres With句」と検索するとバージョン12以前の情報がHITすることもあるので、バージョン確認大事。

非immutable関数とは?

ついでに「非immutable関数」というものが何なのかというと、こちらの資料が参考になります。

www.slideshare.net

特定の関数が「非immutable関数」かどうかを調べたい場合は、こちらのクエリで確認できます。

select provolatile, proname from pg_proc
. .