我们继续关注即将发布的 PostgreSQL 16 的消息。第三届 CommitFest 于 12 月初结束。让我们看看结果。
如果您错过了之前的 CommitFest,请查看我们的评论:2022-07、2022-09 。
以下是我想谈的补丁:
- meson:一个新的源代码构建系统
- 文档:事务处理的新篇章
- psql: \d+ 表示分区表中的外部分区
- psql:扩展查询协议支持
- 物化视图上的谓词锁
- 跟踪索引和表的上次扫描时间
- pg_buffercache:一个新函数 pg_buffercache_summary
- walsender 在进程状态中显示数据库名称
- 减少冻结元组的 WAL 开销
- 空闲时功耗降低
- postgres_fdw:COPY 的批处理模式
- 使 GUC 基础设施现代化
- 哈希索引构建优化
- MAINTAIN ― 表维护的新权限
- SET ROLE:更好的角色变更管理
- 支持 pg_hba.conf 和 pg_ident.conf 中的文件包含指令
- pg_hba.conf 中的正则表达式支持
meson:一个新的源代码构建系统
提交:e6927270,4c72102e _
早在 9 月份,Meson 支持就以提交的方式首次引入。随后又进行了数十次提交。又有几十人紧随其后。12 月初,提交了描述新构建过程的文档部分。还有一个wiki 页面,其中解释了引入新构建工具的决定背后的原因。原因之一是为了简化为 Windows 系统构建服务器,并最终能够完全停止支持来自 /src/tools/msvc 的 PostgreSQL 自己的构建工具。
新的构建系统将与 autoconf 和 make 一起提供,没有计划取代旧的工具。
但是,我专门使用 Meson 为本文构建了全新的 PostgreSQL 16 测试环境。在 Ubuntu 上,构建过程如下:
$ git clone git://git.postgresql.org/git/postgresql.git $ cd postgresql $ meson setup build --prefix=/home/pal/pg16 -Dpgport=5416 $ cd build $ ninja $ ninja install
复制
除了安装位置和服务器端口外,我将所有内容都保留为默认值。
剩下的就是初始化集群并启动服务器,无论使用何种构建工具,您都可以按照相同的方式进行操作。
文档:事务处理的新篇章
提交:66bc9d2d
文档中增加了一个新章节:74.事务处理。它位于 Internals 部分,简要概述了什么是虚拟和真实交易标识符,它们在 中的显示方式pg_locks
,以及子交易和两阶段交易的工作方式。
psql: \d+ 表示分区表中的外部分区
提交:bd95816f
对于分区表,\d+ 命令将用单词标记外部表的部分FOREIGN
。
\d+ data
复制
Partitioned table "public.data" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description -----------+------+-----------+----------+---------+----------+-------------+--------------+------------- data_year | text | | | | extended | | | Partition key: LIST (data_year) Partitions: data_2020 FOR VALUES IN ('2020'), FOREIGN, data_2021 FOR VALUES IN ('2021'), FOREIGN, data_2022 FOR VALUES IN ('2022')
复制
psql:扩展查询协议支持
提交:5b66de34
直到现在,psql 还没有直接支持扩展查询协议。因此,参数化查询只能间接执行,例如使用PREPARE
语句。
现在该\bind
命令已添加到 psql 以将值绑定到下一个查询的参数。它是这样工作的:
SET log_statement='all'; \bind 42 'Answer: ' SELECT $2||$1;
复制
?column? ------------ Answer: 42 (1 row)
复制
\! tail -2 logfile
复制
2022-12-05 12:58:05.924 MSK [16566] LOG: execute : SELECT $2||$1; 2022-12-05 12:58:05.924 MSK [16566] DETAIL: parameters: $1 = '42', $2 = 'Answer: '
复制
仅实现了扩展查询协议的一小部分功能,但该倡议非常受欢迎。
物化视图上的谓词锁
提交:43351557
谓词锁用于确保具有SERIALIZABLE
隔离级别的事务的一致性。它们从未被设计为使用REFRESH MATERIALIZED VIEW
命令更新物化视图,因为它专门锁定视图以防止任何并发访问异常。
但是,当使用CONCURRENTLY
参数更新且没有谓词锁时,具有隔离级别的事务SERIALIZABLE
可能会出现写偏斜。现在问题解决了。
跟踪索引和表的上次扫描时间
提交:c0374718
除了计算表和索引扫描之外,累积统计系统现在还记录最后一次记录扫描的时间和日期。此数据存储在中的last_seq_scan
和last_idx_scan
列中pg_stat_all_tables
以及中的last_idx_scan
列中pg_stat_all_indexes
。
SELECT seq_scan, last_seq_scan, idx_scan, last_idx_scan FROM pg_stat_all_tables WHERE relid = 'tickets'::regclass;
复制
seq_scan | last_seq_scan | idx_scan | last_idx_scan ----------+-------------------------------+----------+------------------------------- 23 | 2022-12-07 15:17:57.261575+03 | 2 | 2022-12-05 14:59:53.564968+03 (1 row)
复制
SELECT indexrelname, idx_scan, last_idx_scan FROM pg_stat_all_indexes WHERE relid = 'tickets'::regclass;
复制
indexrelname | idx_scan | last_idx_scan ----------------------+----------+------------------------------- tickets_pkey | 2 | 2022-12-05 14:59:53.564968+03 tickets_book_ref_idx | 0 | (2 rows)
复制
如果没有实施专门的监控系统,它可能有助于分析索引和表的使用情况。
pg_buffercache:一个新函数 pg_buffercache_summary
提交:2589434a
pg_buffercache 扩展现在可以显示聚合的缓冲区缓存数据:
CREATE EXTENSION pg_buffercache; SELECT * FROM pg_buffercache_summary()\gx
复制
-[ RECORD 1 ]--+------------------ buffers_used | 2544 buffers_unused | 13840 buffers_dirty | 38 buffers_pinned | 0 usagecount_avg | 2.183176100628931
复制
我们以前通过聚合视图来获取这些数据pg_buffercache
,但新功能不会锁定缓冲区,因此它更便宜并且可以轻松集成到监控系统中。
walsender 在进程状态中显示数据库名称
提交:af205152
walsender
是处理复制协议连接的进程。对于物理复制或备份,walsender
连接到一个实例,但不连接到特定的数据库。但是,当您创建逻辑复制订阅时,发布者会创建一个逻辑复制槽,并walsender
连接到创建发布的数据库。
该补丁在逻辑复制的情况下将数据库的名称添加到walsender
进程描述中,这使得监控这些进程更加方便。
16(sub)=# CREATE SUBSCRIPTION sub CONNECTION 'port=5416 user=postgres dbname=demo' PUBLICATION pub;
复制
NOTICE: created replication slot "sub" on publisher CREATE SUBSCRIPTION
复制
16(pub)=# \! ps -o pid,command --ppid `head -n 1 /home/pal/pg16/data/postmaster.pid`
复制
PID COMMAND 38514 postgres: checkpointer 38515 postgres: background writer 38517 postgres: walwriter 38518 postgres: autovacuum launcher 38519 postgres: logical replication launcher 38522 postgres: postgres demo [local] idle 38662 postgres: walsender postgres demo [local] START_REPLICATION
复制
此处,walsender 进程状态显示演示数据库名称。
减少冻结元组的 WAL 开销
提交:9e540599
Peter Geoghegan正在研究主动元组冻结。目的很明确:为了避免交易柜台回绕,需要提前开始冻结。然而,较早的冻结会导致更大的 WAL 卷并增加相关的开销(WAL 复制和归档)。
在这个补丁中,Peter 提议更紧凑地形成 WAL 冻结记录(大约 5 倍)。
空闲时功耗降低
提交:cd4329d9,05a7be93 _
当主服务器空闲时,物理副本上的启动进程仍然每5秒唤醒一次,检查promote_trigger_file中指定的文件是否出现。但是还有其他机制可以提升副本:pg_ctl promote
以及pg_promote
功能。为了减少此类唤醒的资源消耗,删除了promote_trigger_file参数。
对进程进行了类似的工作walreceiver
,每秒唤醒 10 次,检查它是否需要做某事。现在,进程会提前计算下一次启动的时间。
postgres_fdw:COPY 的批处理模式
提交:97da4824
在第 14 版中,批量插入记录首次成为可能。批量大小由外部服务器或表级别的 batch_size 参数设置。但是,它仅针对INSERT
命令实施。此补丁为该COPY FROM
命令添加了对批量粘贴模式的支持。
让我们比较一下不同命令的插入速度。为此,我首先在 postgres 数据库中创建一个空的预订表,我们将向其中插入数据。
postgres=# CREATE TABLE public.bookings ( book_ref char(6), book_date timestamptz, total_amount numeric(10,2) );
复制
在同一集群的演示数据库中,让我们为预订表创建一个外部表。
CREATE EXTENSION postgres_fdw; CREATE SERVER srv FOREIGN DATA WRAPPER postgres_fdw OPTIONS (dbname 'postgres', batch_size '1'); CREATE USER MAPPING FOR postgres SERVER srv OPTIONS (user 'postgres'); CREATE FOREIGN TABLE bookings_remote ( book_ref char(6), book_date timestamptz, total_amount numeric(10,2) ) SERVER srv OPTIONS (schema_name 'public', table_name 'bookings');
复制
批量大小在服务器级别设置为 1,这意味着禁用批量模式并且一次发送一条记录。
让我们将演示数据库中的预订表内容转储到一个文件中:
\COPY bookings TO 'bookings.txt'
复制
现在,将文件内容上传到外表并测量时间:
\timing on \COPY bookings_remote FROM 'bookings.txt'
复制
COPY 2111110 Time: 57327,152 ms (00:57,327)
复制
插入略多于 200 万行的数据花了将近一分钟的时间。将批量大小设置为 100 并重复测试:
TRUNCATE bookings_remote; ALTER SERVER srv OPTIONS (SET batch_size '100'); \COPY bookings_remote FROM 'bookings.txt'
复制
COPY 2111110 Time: 8780,000 ms (00:08,780)
复制
插入速度提升6倍以上!
奇怪的是,该INSERT
命令在批处理模式下运行得更快:
TRUNCATE bookings_remote; INSERT INTO bookings_remote SELECT * FROM bookings;
复制
INSERT 0 2111110 Time: 6669,504 ms (00:06,670)
复制
所以在COPY
命令插入的时候,还有优化的空间!此外,如果能教postgres_fdw
你使用批处理模式来修改和删除行,而不仅仅是读取和插入,那就太好了。
使 GUC 基础设施现代化
提交:f13b2088、3057465a、407b50f2、9c911ec0 _ _ _
这一系列提交优化了存储并加快了对配置参数(包括用户生成的参数)的访问。
优化在 Tom Lane 在开始讨论的信中给出的示例中最为明显:
do $$ begin for i in 1..10000 loop perform set_config('foo.bar' || i::text, i::text, false); end loop; end $$;
复制
在我的电脑上,在 PostgreSQL 15 中创建一万个用户参数大约需要 6 秒,应用补丁后,时间缩短到 30 毫秒左右。
哈希索引构建优化
提交:e09d7a12,d09dbeb9
在构建哈希索引时,值仅按桶号排序。如果您另外按值排序,则插入后续值会更快。
第一次提交是在 7 月,第二次是在 11 月。到目前为止,哈希索引构建速度提高了 5-15%。
MAINTAIN ― 表维护的新权限
提交:60684dd8
表和物化视图的许多维护操作不受权限限制,通常只对对象所有者和超级用户可用。
PostgreSQL 16 引入了MAINTAIN
权限,可以在物化视图和表上授予权限,包括系统视图和表:
GRANT MAINTAIN ON pg_class, pg_attribute, pg_type TO alice;
复制
\dp
输出为此权限使用 m 字符:
\dp pg_catalog.pg_class Access privileges Schema | Name | Type | Access privileges | Column privileges | Policies ------------+----------+-------+----------------------------+-------------------+---------- pg_catalog | pg_class | table | postgres=arwdDxtm/postgres+| | | | | =r/postgres +| | | | | alice=m/postgres | |
复制
此特权授予哪些操作?这些包括执行命令ANALYZE
, VACUUM
(包括VACUUM FULL
)CLUSTER
、REINDEX
、REFRESH MATERIALIZED VIEW
和LOCK TABLE
。
此外,还添加了一个预定义的 pg_maintain 角色。此角色的成员资格授予MAINTAIN
对数据库中所有关系的特权。这允许您将维护特权授予无权在数据库中执行 DDL 和 DML 操作的常规角色。
最初的补丁建议为VACUUM
和增加两个权限ANALYZE
,但最终社区决定使用MAINTAIN
具有更广泛维护能力的权限。
SET ROLE:更好的角色变更管理
提交:3d14e171
此补丁继续努力构建更强大的角色和权限管理系统。上一篇文章谈到了授予角色成员资格和继承特权。
新补丁引入了使用SET ROLE
命令切换到另一个角色。假设我们决定将alice
角色包含在pg_read_all_data
启用特权继承的情况下:
postgres=# GRANT pg_read_all_data TO alice WITH INHERIT TRUE;
复制
该alice
角色现在可以使用pg_read_all_data
特权。但是没有什么可以停止alice
切换角色pg_read_all_data
并开始代表它创建对象:
postgres=# \c - alice
复制
You are now connected to database "postgres" as user "alice".
复制
alice=> CREATE TABLE t (id int);
复制
CREATE TABLE
复制
alice=> \dt t
复制
List of relations Schema | Name | Type | Owner --------+------+-------+------------------ public | t | table | pg_read_all_data
复制
其实是有的。要创建对象,pg_read_all_data
角色必须CREATE
在某些模式中具有特权,例如在public
. 并且从 PostgreSQL 15 开始,伪角色public
不再有这个权限。至于上面的例子,我必须提前运行以下命令:
postgres=# GRANT CREATE ON SCHEMA public TO public;
复制
然而,在某些情况下可能不希望切换到另一个角色。如果我们提供角色的成员资格INHERIT TRUE
,那么为什么要切换呢?在新版本中,这可以通过相同的GRANT
命令来禁止:
postgres=# GRANT pg_read_all_data TO alice WITH INHERIT TRUE, SET FALSE;
复制
Alice 现在可以使用pg_read_all_data
权限,但无法切换到它。
alice=> SET ROLE pg_read_all_data;
复制
ERROR: permission denied to set role "pg_read_all_data"
复制
切换到角色的能力存储在表格的set_option
列中,在和pg_auth_members
旁边。inherit_option
admin_option
SELECT roleid::regrole, member::regrole, grantor::regrole, admin_option, inherit_option, set_option FROM pg_auth_members WHERE member = 'alice'::regrole\gx
复制
-[ RECORD 1 ]--+----------------- roleid | pg_read_all_data member | alice grantor | postgres admin_option | f inherit_option | t set_option | f
复制
支持 pg_hba.conf 和 pg_ident.conf 中的文件包含指令
提交:a54b658c
配置文件 pg_hba.conf 和 pg_ident.conf 以及 postgresql.conf 现在支持包含其他文件的指令:include
, include_if_exists
, include_dir
.
包含文件名和规则/地图编号的列已添加到pg_hba_file_rules
和pg_ident_file_mappings
:
SELECT * FROM pg_hba_file_rules WHERE file_name LIKE '%hba_ident_test.conf' \gx
复制
-[ RECORD 1 ]--------------------------------- rule_number | 1 file_name | /home/pal/pg/hba_ident_test.conf line_number | 1 type | local database. | {all} user_name | {alice} address | netmask | auth_method | peer options | {map=m1} error |
复制
SELECT * FROM pg_ident_file_mappings WHERE file_name LIKE '%ident_test.conf' \gx
复制
-[ RECORD 1 ]----------------------------- map_number | 1 file_name | /home/pal/pg/ident_test.conf line_number | 1 map_name. | m1 sys_name. | student pg_username | alice error |
复制
pg_hba.conf 中的正则表达式支持
提交:8fea8683,a9039713,fc579e11
pg_hba.conf 支持用户名和数据库名的正则表达式。如果这些字段中的任何一个以斜杠 (/) 开头,则该值被视为正则表达式。
这就是现在的全部。期待一月 CommitFest的结果!
原文标题:PostgreSQL 16: part 3 or CommitFest 2022-11
原文作者:Pavel Luzanov
原文链接:https://postgrespro.com/blog/pgsql/5969929