Hubert 'depesz' Lubaczewski:等待 PostgreSQL 17 – 使用 ALTER TABLE 命令更改生成表达式
内容提要
2024年1月4日,Peter Eisentraut提交了一个补丁,增加了一个新的ALTER TABLE子命令ALTER COLUMN ... SET EXPRESSION,用于更改生成列的生成表达式。该命令会导致表重写,并使用ALTER TABLE机制。该命令需要在AlterTablePass中进行新的传递,并且ADD COLUMN传递必须提前,以便ADD COLUMN和SET EXPRESSION的组合可以工作。作者对此表示有些复杂的感觉,但认为功能很棒,并感谢所有参与者。
延伸解读
新命令的语法与实现机制
PostgreSQL 17 新增的 ALTER TABLE ... ALTER COLUMN ... SET EXPRESSION 子命令,允许直接修改生成列的生成表达式。其语法借鉴了其他 SQL 实现,但并非标准。实现上复用了 SET DATA TYPE 的基础设施,例如重建约束和索引,并需要在 AlterTablePass 中新增一个传递,同时将 ADD COLUMN 传递提前,以支持 ADD COLUMN 与 SET EXPRESSION 的组合使用。
表重写与长时间锁定的代价
使用该命令更改生成表达式会导致表重写,并产生长时间锁定。作者理解这种必要性,因为生成列的值需要根据新表达式重新计算并存储。这意味着在生产环境中执行此类操作时,需考虑对并发访问的影响,可能需要在维护窗口进行,或使用其他策略减少锁定时间。
语法冗长引发的讨论
作者对 SQL 的冗长表示不满,认为 SET EXPRESSION AS 的表述可以更明确,例如改为 SET GENERATED EXPRESSION AS。尽管存在这一小遗憾,作者仍认为该功能非常棒,并感谢所有参与者。这反映了社区对语法清晰性的关注,但功能本身的价值得到了认可。
Q&A
PostgreSQL 17 中如何修改生成列的生成表达式?
使用 ALTER TABLE 命令的 ALTER COLUMN ... SET EXPRESSION 子命令,例如:ALTER TABLE testing ALTER COLUMN when_year SET EXPRESSION AS (EXTRACT(YEAR FROM when_ts)::int4 - 2000);
ALTER TABLE ... SET EXPRESSION 会导致表重写吗?
是的,该命令会导致表重写,并使用通常的 ALTER TABLE 机制,因此会产生长时间锁。
SET EXPRESSION 的实现与哪个现有子命令类似?
实现类似于 SET DATA TYPE 子命令,并利用了其部分基础设施,例如之后重建约束和索引。
为什么 ADD COLUMN 传递需要提前?
因为新的 SET EXPRESSION 命令需要在 AlterTablePass 中新增一个传递,而 ADD COLUMN 传递必须提前,以便 ADD COLUMN 和 SET EXPRESSION 的组合可以工作。
作者对 SET EXPRESSION 的语法有什么看法?
作者认为 SQL 总是很冗长,但在这个例子中本可以多用一个词,比如使用“set generated expression as”可能更清晰。
这个补丁是谁提交的?什么时候提交的?
补丁由 Peter Eisentraut 于 2024 年 1 月 4 日提交,作者是 Amul Sul。