Postgres 即将发布一项令人难以置信的新功能

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

스크립트

00:00:00事实证明,那些说“兄弟,所有东西用 Postgres 就对了”的开发者们
00:00:04在即将发布的 Postgres 19 中显得更加正确了,该版本包含了对图查询的原生支持
00:00:10这是一个非常酷的功能。所以在今天的视频中,我想介绍 Postgres 19 的所有重磅功能
00:00:16并深入探讨图查询,因为我认为它
00:00:21可能会从根本上改变我们设计查询和使用 Postgres 的方式。
00:00:30首先要介绍的是一个叫做 on conflict do select 的功能。如果你想插入一行数据,前提是它尚不存在
00:00:35并且无论是否存在你都想把这行数据作为结果返回,通常你需要
00:00:40两条查询来实现:一条 insert 和一条 select,这是一种非常常见的工作流程。所以在示例中
00:00:45我们说要向 users 的 email 和 name 插入数据,然后给出这些值,接着在
00:00:50末尾我们写上 on conflict for email do nothing returning star。Do nothing 在行已存在时不会返回任何内容
00:00:56所以你需要接着执行一个 select,但连在一起它们就不是原子的。而在 19 中你可以
00:01:03通过一个查询搞定。向 users 插入 email 和 name,然后写上 on conflict email do select
00:01:11returning star。如果你想在同一个查询中进行修改,我们可以写 insert into users,然后再次给出
00:01:16值,接着写 on conflict for the email do select for update returning id and name。由于这是一个单独的
00:01:23语句,它是原子的,你要么插入它,要么每次都选中它,这是一个
00:01:29非常普遍的用例,将会非常有用。接下来是图,但如果你喜欢这个内容,
00:01:34为什么不订阅 better stack 以了解科技领域的最新动态呢。如我之前所说,
00:01:39在我看来这是最重磅的功能。假设你有一个商店的常规模式,拥有客户、
00:01:44订单和产品,外加将它们串联起来的两张连接表,而你想知道某个特定的客户
00:01:50究竟买了哪个产品。在 SQL 中,这需要在所有五张表之间进行一连串的 join,虽然在这里
00:01:56还算可控,但面对更复杂的关联时,它很快就会变得非常难看。不过现在我们
00:02:02可以把所有这些作为一个图来查询,复杂的 join 语法现在可以变成一种全新的图语法。
00:02:08特别是对于复杂的 join,你会在这里看到巨大的优势。我们现在在数据库
00:02:14查看器里,你可以看到我们拥有所有的表:产品、订单、事件,还有
00:02:20客户,以及连接所有这些数据的透视表。我们有订单项
00:02:25和客户订单,现在让我们尝试对所有这些表运行查询。比如说,
00:02:30这里有个叫爱丽丝的用户,我想查出爱丽丝订购的所有东西。为了做到这一点,
00:02:35我得通过一堆不同的 join 查询来连接所有这些表。因此我会运行这个
00:02:41包含四个独立 join 语句的查询,虽然这不一定很难
00:02:46写,但非常丑陋。不过如果我们运行它,你可以看到爱丽丝订购的所有物品——
00:02:51机械键盘和人体工学鼠标。但现在我们可以使用图语法来极大地简化
00:02:57这一切。我们将用新的图语法替换所有这些,然后再次执行它,你就会
00:03:03发现我们得到了相同的记果,如果把这些排成一行,它读起来就会变得更轻松,你可以看到
00:03:07我们只是从客户到客户订单,再到订单、订单项,最后到产品。所以你
00:03:13基本上只需遵循这个简单的流程就能遍历整个图,依我来看这要容易阅读得多得多。
00:03:19如果你也想选择多个列,我们同样可以做到,我们在顶部有相同的
00:03:23图查询,但接着我们可以在底部定义列,然后选择我们想要显示的
00:03:27所有列,执行后我们就能在底部看到结果。现在,除非我们一开始就
00:03:32创建了图,否则这些都不会起作用。我用来生成该图的
00:03:37查询在这里,我们说 create property graph,然后给它起个名字 my shop,接着
00:03:42勾勒出顶点表,也就是客户、订单和产品,这些是
00:03:47真正持有数据的对象,然后我们有边表,这些是
00:03:52真正建立连接的对象,也就是我们的透视表,在我们的例子中就是客户订单和订单
00:03:57项。它的语法超级简单,我们说对于客户订单,源是客户,
00:04:02目标是订单;对于订单项,源是订单,目标是产品。有了这些,
00:04:08每当我们运行图查询时,postgres 就会知道这些关系是如何定义的。
00:04:14为了让它工作,你需要创建一个图,但这不会创建新表之类的内容,
00:04:19你只需指向你已有的五张表,其中真正持有数据的三张表变成
00:04:23顶点,两张连接表变成边,它的工作方式更像是一个视图,所以你先前的模式
00:04:29保持完全不变,你只是在上面获得了这个附加功能。所以在这里我们要
00:04:35说 create property graph,将其命名为 my shop,然后开始描述该关系
00:04:40是如何实际运作的,这就是我们为图做所有工作的地方,这意味着查询
00:04:45可以比各自的 join 语法精简得多。那么,这是 neo4j 的替代品吗?如果你想要一个
00:04:52图数据库是因为你需要图存储和遍历性能,那么不是,专用的图
00:04:58数据库可能仍然是更好的选择。但如果你想要它是因为在 sql 中编写 10 张表的 join
00:05:03既痛苦又丑陋,那么它绝对会让你受益,并且相比之下会好用得多。
00:05:09第三个新功能是 repack,这个功能旨在取回磁盘空间。postgres
00:05:15从不就地更新行,它会写入一个新版本并将旧版本留在后面,而 vacuum 仅仅
00:05:21将死空间标记为可重用,所以你的磁盘占用实际上永远不会下降。repack 会将整张表重写
00:05:27到一个没有浪费空间的新文件中,这才是把空间还给
00:05:33操作系统的方式。你其实已经可以通过 vacuum full 来做到这一点,但这会在整个重写过程中
00:05:38对表加锁,所以对于任何巨大的表你根本不会运行它,这也是为什么人们会安装
00:05:42像 pg repack 这样的扩展。但现在我们直接将其内置到了 postgres 中,在其中使用 concurrently 关键字
00:05:49就能在 repack 工作的同时保持表的可读写。不过这里需要注意的一点是,
00:05:54你需要有足够的可用磁盘空间来存放表的第二个副本及其所有索引,所以你需要
00:06:00备用空间来真正回收更多空间。所以这并不是 pg repack 的完全替代品,但对于
00:06:06普通表而言,它无需扩展就能完成工作。好了,接下来我们要对
00:06:1119 版本中的其余功能进行快速连珠炮式的介绍。首先是查询提示,postgres 决定如何实际运行你的
00:06:17查询,而且它可能会随着时间改变主意,所以一个用了一年都正常的查询突然变慢了,
00:06:22而你的代码没有任何改变。一个名为 pg plan advice 的新模块允许你在查询仍然很快时捕获执行计划
00:06:28并将其固定,这样它就会一直保持那种状态。jit 现在默认关闭了,postgres 会将繁重的查询
00:06:36编译为机器码,但它根据规划器的成本估算来决定何时费心去做,而发行说明
00:06:41指出这种成本计算实际上并不可靠,因此它会在那些实际上不需要它的
00:06:46查询上触发。此外,vacuum 现在可以使用多个工作线程并行清理你的索引,这样可以减少
00:06:52清理大表花费的时间。不过你确实需要自己开启这个功能。你知道当你添加一列
00:06:58去执行 select,然后又必须将同一列添加到 group by 中时,它会为你处理好这一切。
00:07:03并且 copy 关键字现在可以直接导出为 json,所以如果你一直在转储 csv 并在事后进行转换,
00:07:09你可以停止这么做了。这就是 postgres 19 beta 2 在 7 月份登陆的情况,最终版本
00:07:15预计在 9 月或 10 月左右发布,所以如果你运行的是任何旧版本,现在就值得把 beta 版拉下来
00:07:21并针对它进行测试。如果你想了解更多关于 postgres 的信息,你其实可以查看
00:07:25对 pg durable 的剖析,它将持久工作流直接放进了 postgres 中。我是来自
00:07:31betterstack 的 warren,感谢您的观看,我们下期再见

핵심 요약

Postgres 19 通过引入原生图查询、原子级冲突选择、在线空间回收及执行计划固定等核心功能,显著简化了复杂数据操作并提升了维护效率。

하이라이트

  • Postgres 19 引入了对图查询的原生支持,允许通过属性图语法替代复杂的多表连接操作。

  • 新功能 ON CONFLICT DO SELECT 实现了单条查询中的原子性插入或查找并返回结果。

  • 内置的 REPACK 功能支持使用 CONCURRENTLY 关键字在线重写表,从而在清理磁盘空间的同时保持表的可读写。

  • PG Plan Advice 模块允许捕获并固定执行计划,避免查询性能随时间意外发生变化。

  • COPY 关键字现在支持直接将数据导出为 JSON 格式,省去了后续的转换步骤。

타임라인

Postgres 19 概述与原子冲突查询

  • Postgres 19 包含对图查询的原生支持,改变了复杂关联查询的设计方式。
  • 新增的 ON CONFLICT DO SELECT 语法解决了以往需要两条独立查询才能完成的原子性插入或查找需求。
  • 该语句确保了操作的原子性,无论数据是否存在都能单次返回结果或执行加锁修改。

开发者在插入数据时如果要求行尚不存在并返回结果,通常需要组合 INSERT 和 SELECT,但两者组合并不具备原子性。19 版本通过在冲突处理时直接执行 SELECT,将这一常见工作流程合并为单条原子语句。这不仅简化了代码逻辑,还提供了诸如 FOR UPDATE 的修改选项。

原生图查询语法与属性图创建

  • 图查询通过属性图语法将多张表的复杂 JOIN 简化为单一的线性流遍历。
  • 使用 CREATE PROPERTY GRAPHS 可以将现有的实体表定义为顶点,连接表定义为边。
  • 原生图查询适用于简化复杂的 SQL 关联,但不能完全替代专用的图数据库。

面对客户、订单、产品及多张透视表的复杂关联时,传统的 SQL 需要编写多个丑陋的 JOIN 语句。Postgres 19 允许定义属性图,将持有数据的表作为顶点,透视表作为边。通过简单的图语法,开发者可以轻松遍历关系并选择所需列,极大地提高了代码的可读性。

磁盘空间回收与 REPACK 功能

  • 传统的 VACUUM 仅标记死空间可重用,无法缩减文件系统上的实际磁盘占用。
  • 内置的 REPACK 功能通过重写表到新文件来将空间真正还给操作系统。
  • 使用 CONCURRENTLY 关键字可以在重写过程中保持表正常进行读写操作。

由于 Postgres 不会就地更新行,磁盘占用通常只会增加。虽然 VACUUM FULL 可以回收空间但会全程加锁,而内置的 REPACK 通过 CONCURRENTLY 允许在线完成这一过程。不过该操作需要足够的临时磁盘空间来存放表的第二个副本及其索引。

其他重磅功能与版本发布计划

  • PG Plan Advice 模块允许锁定执行计划,防止查询随时间意外变慢。
  • JIT 编译由于成本估算不可靠现在默认关闭,VACUUM 支持多线程并行清理索引。
  • Postgres 19 最终版本预计在 9 月或 10 月发布,当前测试版已可用于测试。

除了主要的新特性外,19 版本还带来了多项实用改进。例如,COPY 关键字现在支持直接导出 JSON 格式,省去了转储 CSV 后的转换工作。同时,默认关闭的 JIT 编译和并行索引清理等优化共同提升了整体数据库管理的效率。

커뮤니티 글

모든 글 보기