内容提要
PostgreSQL 11至18版本每年发布,SQL功能持续增强。文章精选了窗口函数GROUPS模式、FETCH WITH TIES、递归CTE的SEARCH/CYCLE、uuidv7、多范围类型、JSON路径语言、生成列、MERGE语句等关键改进,并提及增量备份等运维特性。这些功能解决了实际SQL编写问题,推动PostgreSQL成为最受欢迎的数据库。
延伸解读
版本演进与商业驱动
文章统计了PG 11至18各版本的功能分类,SQL改进数量最少,而运维和性能类占主导。这反映了云厂商(如Amazon、Google、Microsoft)对PostgreSQL的投入重点:易运维、可扩展和高可用。复制与高可用功能增长最快,从PG 11的3项增至PG 17的8项。理解这一趋势有助于用户把握PostgreSQL的发展方向,在选型时关注运维和复制能力。
窗口函数与排序的实用技巧
PG 11引入的GROUPS窗口模式和PG 14的EXCLUDE子句,为处理并列排名提供了标准SQL方案。例如,EXCLUDE TIES可在计算累计值时排除并列行,避免重复计数。PG 13的FETCH FIRST WITH TIES则能自动包含并列行,无需手动扩展结果集。这些功能简化了复杂排序和排名查询的编写,提升了SQL表达的精确性。
数据建模的新选择
PG 14的多范围类型(multirange)和range_agg()聚合函数,为处理不连续时间段提供了优雅方案。例如,乐队成员多次加入离开的情况,可用tstzmultirange存储多个子范围,并通过@>操作符快速查询某时刻的成员。PG 15的NULLS NOT DISTINCT允许唯一约束将NULL视为相等,适合可选唯一标识符场景。PG 18的虚拟生成列则提供了不占存储的表达式列,适合计算成本低且写入频繁的场景。
升级注意事项
文章特别提醒,PG 18改变了pg_trgm扩展的trigram生成方式,旧版本构建的索引在升级后可能无法正确匹配,需立即重建。此外,PG 12起CTE默认内联,可能改变查询性能,需根据情况使用MATERIALIZED或NOT MATERIALIZED提示。升级前应检查相关索引和查询计划,避免性能回退或数据遗漏。
Q&A
PostgreSQL 11到18版本中,有哪些SQL功能改进?
PostgreSQL 11到18版本中,SQL功能持续增强,包括窗口函数GROUPS模式、FETCH WITH TIES、递归CTE的SEARCH/CYCLE、uuidv7、多范围类型、JSON路径语言、生成列、MERGE语句等。
PostgreSQL中窗口函数GROUPS模式和EXCLUDE子句有什么作用?
GROUPS模式是窗口函数的一种帧模式,它按ORDER BY值相同的行分组(peer groups),适用于排名或并列数据。EXCLUDE子句(PG 14)可以从帧中排除特定行,如EXCLUDE CURRENT ROW、EXCLUDE TIES或EXCLUDE GROUP,其中EXCLUDE TIES会保留当前行但移除其他并列行。
FETCH FIRST n ROWS WITH TIES和LIMIT n有什么区别?
LIMIT n只返回恰好n行,如果截断处有并列,则任意选择。FETCH FIRST n ROWS WITH TIES会额外返回所有与最后保留行并列的行,确保并列数据完整。WITH TIES是SQL标准语法,仅适用于FETCH FIRST,LIMIT没有ties扩展。
PostgreSQL 14中递归CTE的SEARCH和CYCLE子句有什么用途?
SEARCH子句控制递归CTE的遍历顺序,支持DEPTH FIRST(深度优先)和BREADTH FIRST(广度优先)。CYCLE子句用于检测和停止循环,通过设置is_cycle标志和path列来避免无限递归。
PostgreSQL 18中uuidv7()相比gen_random_uuid()有什么优势?
uuidv7()生成时间可排序的UUID v7,前48位编码毫秒时间戳,因此按插入顺序排序时,UUID列也按字典序排列,有利于B-tree索引局部性和聚集写入。对于新架构中UUID主键且插入负载高的场景,uuidv7()是更好的选择。
PostgreSQL 14中多范围类型和range_agg()有什么用途?
多范围类型(如tstzmultirange)是子范围的集合,用于表示有间隙的区间。range_agg()聚合函数将多个范围合并为一个多范围,自动合并重叠或相邻的子范围,保留间隙。这适用于建模如乐队成员多次加入离开的情况,配合EXCLUDE约束或唯一约束使用。
PostgreSQL 17内置的C.UTF-8排序规则有什么特点?
C.UTF-8排序规则是内置的,与操作系统无关,按Unicode码点排序,跨平台一致且不可变,速度接近C locale。适用于需要可复现排序的环境,如多区域部署、CI管道或逻辑复制。但码点排序不如语言感知的ICU排序自然,因此面向用户的排序建议使用ICU。
PostgreSQL 12中生成列(STORED)和18中虚拟生成列(VIRTUAL)有什么区别?
STORED生成列在写入时计算并存储,占用磁盘空间,可被索引;VIRTUAL生成列在查询时计算,不占用存储,但不可直接索引,需使用函数索引。选择STORED适合表达式昂贵或需要索引的场景,VIRTUAL适合表达式便宜且写入吞吐重要的场景。
PostgreSQL 15中NULLS NOT DISTINCT在唯一约束中有什么作用?
默认情况下,唯一约束允许任意数量的NULL值,因为NULL不等于NULL。NULLS NOT DISTINCT使所有NULL值视为相等,因此最多允许一个NULL。适用于可选唯一标识符(如IBAN)的列,其中NULL表示未分配,两个未分配的行应冲突。
PostgreSQL 15的MERGE语句和17的扩展有什么功能?
MERGE语句(PG 15)在一个语句中实现插入、更新或删除,基于源数据与目标匹配情况。PG 17增加了WHEN NOT MATCHED BY SOURCE分支,处理目标中有而源中没有的行,并支持RETURNING和merge_action()函数报告每个受影响行的操作类型。