我的应用程序当前使用 PostgreSQL 11.6。今天,我在虚拟机上测试了 PostgreSQL 12.1,结果令人震惊:一个重要查询在版本 11(同一虚拟机)上需要 100 毫秒,现在在 Postgres 12 上只需要大约 36 秒。这慢了 300 多倍。
我怀疑 CTE 的新处理方式,即MATERIALIZED,NOT MATERIALIZED是造成这种情况的原因。
如果我将每个 CTE 更改为MATERIALIZED,查询时间将从 36 秒减少到 6 秒。明显好一些,但仍然比版本 11 慢 50 倍以上。
如果我没猜错的话,在 PostgreSQL 12 中你有两个替代选项:
MATERIALIZEDCTE 只执行一次,但你失去了索引的好处NOT MATERIALIZED索引的好处,但每次访问其结果时都会执行您的 CTE。那是对的吗?
是否有任何技巧,例如返回 Postgres 11 行为的特殊设置?或者是处理此问题的唯一方法,手动评估每个 CTE 是否MATERIALIZED更好NOT MATERIALIZED?
我想,很多时候并不清楚哪种方式更好。我的应用程序包含数百个 CTE,其中许多都执行表查询和昂贵的函数调用(文档中的示例,他们说这NOT MATERIALIZED更好)。
编辑: 我检查过的内容以使结果具有可比性:
vacuum analyze结果EXPLAIN ANALYZE …