Обсуждение: Avoid calling SetMatViewPopulatedState if possible
Hi, During refresh matview, we call SetMatViewPopulatedState unconditionally even if the value doesn't change. Attach a small patch to optimize it. -- Regards, ChangAo Chen
Вложения
Hi, On 10.04.2026 05:36, cca5507 wrote: > During refresh matview, we call SetMatViewPopulatedState unconditionally even > if the value doesn't change. Attach a small patch to optimize it. Thanks for sharing this patch. While being a simple patch, it would be good to know what actual use cases this change improves on and by how much. Can you share a test case and/or performance data? -- David Geier
Hi, Thanks for your reply! > While being a simple patch, it would be good to know what actual use > cases this change improves on and by how much. Can you share a test case > and/or performance data? The improvement of performance is small, so it's hard to observe it. But I think the patch is still useful because we can avoid generating dead pg_class tuple: create table t(a int); create materialized view m as select a from t; create unique index on m(a); select ctid from pg_class where relname = 'm'; refresh materialized view concurrently m; select ctid from pg_class where relname = 'm'; Before the patch, the ctid will change every time we refresh the matview. -- Regards, ChangAo Chen
On 05.05.2026 13:58, cca5507 wrote: >> While being a simple patch, it would be good to know what actual use >> cases this change improves on and by how much. Can you share a test case >> and/or performance data? > > The improvement of performance is small, so it's hard to observe it. But I think > the patch is still useful because we can avoid generating dead pg_class tuple: > > create table t(a int); > create materialized view m as select a from t; > create unique index on m(a); > select ctid from pg_class where relname = 'm'; > refresh materialized view concurrently m; > select ctid from pg_class where relname = 'm'; > > Before the patch, the ctid will change every time we refresh the matview. Yeah, that's kind of what I had in mind as I wasn't expecting the performance to matter much here. Avoiding the bloat seems generally reasonable. But refreshing a materialized view doesn't only change relispopulated but also columns like relfilenode, relpages, relhasindex, etc. Doesn't changing these columns during REFRESH MATERIALIZED VIEW make your optimization applicable in a lot less cases? I'm actually wondering why it works at all, even in the example you gave. Because I thought that even when nothing has changed the pg_class row is updated for more columns than just relispopulated. -- David Geier
> But refreshing a materialized view doesn't only change relispopulated > but also columns like relfilenode, relpages, relhasindex, etc. Doesn't > changing these columns during REFRESH MATERIALIZED VIEW make your > optimization applicable in a lot less cases? I don't think so. If we can skip SetMatViewPopulatedState(), we avoid generating a dead pg_class tuple in all cases. > I'm actually wondering why it works at all, even in the example you > gave. Because I thought that even when nothing has changed the pg_class > row is updated for more columns than just relispopulated. "refresh materialized view concurrently" is done by doing DELETE + INSERT to the matview directly, so only relispopulated will change before the patch. After the patch, the pg_class row don't change anymore. -- Regards, ChangAo Chen