+8613426109659
webmaster@21cto.com

PostgreSQL 18 中的新功能

数据库 0 32 14小时前
图片

PostgreSQL 18 于2025 年 9 月 25 日正式发布

毫无疑问,最重要的变化是全新的异步 I/O (AIO) 子系统。然而,本文将重点介绍那些将影响开发人员日常工作的功能,首先是原生 UUID v7 支持。

原生 UUID v7 支持


  • 提交:78c5e141e
  • 文档:https://www.postgresql.org/docs/18/datatype-uuid.html


PostgreSQL 18 引入了uuidv7()生成 UUID 版本 7 值的函数。

这项原生支持几乎终结了长期以来关于使用SERIAL/IDENTITY类型还是 UUID 作为主键的争论。UUIDv7 兼具两者的优势:既保留了 UUID 的全局唯一性,又具备序列化键的良好性能。

-- Generate a UUIDv7SELECT uuidv7();
-- Create a table using UUIDv7 as primary keyCREATE TABLE orders (    id UUID PRIMARY KEY DEFAULT uuidv7(),    customer_id INT,    total DECIMAL(10,2),    created_at TIMESTAMP DEFAULT NOW());

虚拟生成的列


  • 提交:83ea6c540
  • 文档:
    https://www.postgresql.org/docs/18/sql-createtable.html#SQL-CREATETABLE-PARMS-GENERATED-STORED


生成列最初是在 PostgreSQL 12 时开始引入的,但当时只提供了STORED选项,这意味着生成的列在写入时会存储并占用磁盘空间。添加STORED生成的列将重写整个表。

PostgreSQL 18 引入了该VIRTUAL选项,并将其作为生成列的默认行为。这些列在读取时计算其值,而不是在写入时。这是一种更常见的方法,将其作为默认行为可以使 PostgreSQL 与其他主流数据库保持一致。

-- Create table with virtual generated columnCREATE TABLE employees (    id SERIAL PRIMARY KEY,    first_name TEXT NOT NULL,    last_name TEXT NOT NULL,    salary DECIMAL(10,2),    -- You can also skip VIRTUAL since it's the default option    annual_salary DECIMAL(12,2) GENERATED ALWAYS AS (salary * 12) VIRTUAL);-- Insert data (generated columns are computed automatically)INSERT INTO employees (first_name, last_name, salary) VALUES    ('John''Doe'5000.00),    ('Jane''Smith'6500.00);SELECT first_name, last_name, salary, annual_salaryFROM employees;
虚拟列的优点:

  • 节省空间:对于不需要物理存储的派生数据,虚拟列消除了冗余的磁盘使用。

  • 动态计算:某些计算受益于在查询时执行,特别是当它们依赖于当前系统状态时。


另一方面,STORED对于很少改变的繁重计算来说,生成的列仍然很有价值,其中重复计算的性能成本超过了存储问题。

但是,正如提交中提到的,存在一些限制。最明显的限制是不能在VIRTUAL生成的列上创建索引。

顺便说一句,PostgreSQL 18 还增加了对逻辑复制(提交文档)中生成列的支持。此功能也仅适用于STORED生成列。

返回中的旧值和新值


  • 提交:80feb727c
  • 文档:https://www.postgresql.org/docs/current/dml-returning.html


PostgreSQL 18 增强了RETURNING子句的功能,使其能够在 DML 操作中同时访问旧行值和新行值。

这样一来,就无需再单独执行查询来捕获审计日志中的前后值了。

更新操作

-- Update prices and see both old and new valuesUPDATE productsSET price = price * 1.10WHERE price <= 99.99RETURNING    name,    old.price AS old_price,    new.price AS new_price,    new.price - old.price AS price_change;

冲突时插入

-- Upsert with change trackingINSERT INTO products (name, price) VALUES ('Widget'25.00)ON CONFLICT (name) DO UPDATE SET price = EXCLUDED.priceRETURNING    name,    old.price AS previous_price,    new.price AS current_price,    (old.price IS NULLAS is_new_record;

删除操作

-- Track what was deletedDELETE FROM productsWHERE price < 10.00RETURNING    old.name AS deleted_product,    old.price AS deleted_price;

默认情况下使用 BUFFERS 执行 EXPLAIN ANALYZE

  • 提交:c2a4078eb
  • 文档:https://www.postgresql.org/docs/current/sql-explain.html


PostgreSQL 18 改进了该EXPLAIN命令,以自动提供更详细的查询执行信息。

EXPLAIN ANALYZE现在默认包含缓冲区使用情况信息,无需再添加该BUFFERS选项。此默认行为可帮助开发人员发现原本可能被忽视的 I/O 性能问题:

postgres=# EXPLAIN ANALYZE SELECT * FROM users WHERE age > 25;-- PostgreSQL 18: BUFFERS included automatically Seq Scan on users  (cost=0.00..18.75 rows=125 width=64) (actual time=0.029..0.087 rows=178 loops=1)   Filter: (age > 25)   Rows Removed by Filter89   Buffers: shared hit=12 Planning:   Buffers: shared hit=156 read=3   I/O Timings: shared read=0.024 Planning Time0.512 ms Execution Time0.734 ms

pg_get_acl() 用于权限检查

  • 提交:4564f1ceb
  • 文档:https://www.postgresql.org/docs/18/functions-info.html#FUNCTIONS-INFO-OBJECT-TABLE


PostgreSQL 18 引入了pg_get_acl()以编程方式检索数据库对象访问控制列表 (ACL) 的功能。如果您曾经花时间调试过那些臭名昭著的ERROR 42501: permission denied消息,那么您一定会喜欢有一种统一的方法来检查对象权限。

以前,故障排除权限需要根据对象类型查询不同的系统目录( pg_class) ,每个系统pg_proc目录都有自己的 ACL 格式。pg_namespacepg_attribute

pg_get_acl()函数提供了一个统一的接口,用于从任何数据库对象中检索 ACL,无需记住针对不同对象类型查询哪个目录。

postgres=# SELECT    (pg_identify_object(s.classid,s.objid,s.objsubid)).*,    pg_catalog.pg_get_acl(s.classid,s.objid,s.objsubid) AS aclFROM pg_catalog.pg_shdepend AS sJOIN pg_catalog.pg_database AS d    ON d.datname = current_database() AND       d.oid = s.dbidJOIN pg_catalog.pg_authid AS a    ON a.oid = s.refobjid AND       s.refclassid = 'pg_authid'::regclassWHERE s.deptype = 'a';-[ RECORD 1 ]-----------------------------------------type     | tableschema   | publicname     | testtabidentity | public.testtabacl      | {postgres=arwdDxtm/postgres,foo=r/postgres}

虽然不像新的 AIO 那样引人注目,但这些生活质量的改进使日常开发变得更容易,而且更清晰的界面。

可以看到,pg_get_acl()函灵敏不仅使人类开发人员受益,也将使 AI 代理受益。

作者:天舟

地址:

https://www.bytebase.com/blog/what-is-new-in-postgres-18-for-developer/

评论

我要赞赏作者

请扫描二维码,使用微信支付哦。