PostgreSQL 14及更高版本改进

2022-02-09 08:39:29 浏览数 (1)

PostgreSQL 14及更高版本

本文谈谈PG14中的关键特性及社区中正在谈论PG15及更高版本的内容。

PG14的主要特性

逻辑复制的改进

PG14中对逻辑复制进行了几项增强:

1) 正在进行中的事务中支持逻辑复制

有助于减少大型事务的回放延迟,这里详细进行了介绍:

http://amitkapila16.blogspot.com/2021/07/logical-replication-of-in-progress.html

2) Prepared事务解码

帮助构建多主解决方案的两阶段提交以及帮助减小回放延迟。注意目前订阅方的工作尚未完成,但核心解决方案可以使用它作为输出插件。通过次特性,用户可以构建无冲突复制。详情可参考:

https://www.postgresql.fastware.com/blog/logical-decoding-of-two-phase-commits

3) 对包含DDL的事务进行逻辑解码的性能提升

据观察,有1000个分区的表,对其进行truncate。该事务的解码仅花费1秒,PG14版本前需要4-5分钟。

4) 逻辑复制可以以二进制形式传输数据

这通常更快,如果稍微不需要那么健壮的话

5) 逻辑复制中进行表同步期间允许多个事务,带来的好处:

如果在同步阶段发生错误,将不再需要再次复制整个表

避免了超过CID限制的风险

在整个同步完成之前,不再需要保留WAL

大表的初始化同步阶段花费很长时间,基于这些修改,逻辑复制进行了改进。

6) 通过ADD PUBLICATION和DROP PUBLICATION选项,ALTER SUBSCRIPTION语句现在很容易添加或移除发布

7) 添加了pg_stat_replication_slots系统视图,报告复制槽的活动信息。

帮助用户监控spill或stream的活动以及通过特定复制槽解码的总字节数。

SQL特性

PG14引入和增强了一些有用的特性,其中许多将有助于从其他数据库迁移。

1) CREATE FUNCTION和CREATE PROCEDURE语句现在支持SQL语言

因此函数主体符合SQL标准,可以移植到其他实现。现在可以编写构成不带引号的SQL语句主体,而不是使用PG特定的语法 AS

...
代码语言:javascript复制
CREATE PROCEDURE insert_val (value1 integer, value2 integer)
 LANGUAGE SQL
BEGIN ATOMIC
 INSERT INTO tbl1 VALUES (value1);
 INSERT INTO tbl1 VALUES (value2);
END;

2) 存储过程可以有OUT参数

支持这种参数模式将使得从其他数据库迁移变得更加容易

3) CREATE TRIGGER语法进行了扩展支持OR REPLACE

4) 允许现有的触发器进行有条件的替换,并使迁移更加容易

详细请参考:

https://www.postgresql.fastware.com/blog/create-or-replace-trigger

5) ALTER TABLE语法支持DETACH PARTITION...CONCURRENTLY选项

代码语言:javascript复制
ALTER TABLE [ IF EXISTS ] name
 DETACH PARTITION partition_name [ FINALIZE | CONCURRENTLY ]

在2个运行的事务中,允许一个分区从他的分区表中分离而不阻塞当前查询。因为在2个事务中运行,所以不能在一个事务块中使用。如果第2个事务取消或发生崩溃,则有ALTER TABLE...DETACH PARTITION...FINALIZE,执行最后的步骤。

6) 使用postgres_fdw模块,Truncate可以在外表上执行

7) 改进了下标

扩展和内置数据类型可以完成下标。例如,jsonb可以使用下标:

早期

代码语言:javascript复制
SELECT jsonb_column->'key' FROM table;
UPDATE table
SET jsonb_column = jsonb_set(jsonb_column, '{"key"}', '"value"');

PG14

代码语言:javascript复制
SELECT jsonb_column['key'] FROM table;
UPDATE table
SET jsonb_column['key'] = '"value"';

8) 支持了multirange数据类型

和range数据类型类似,但是允许指定多个、有序、不重叠的range。所有现在的range类型都支持multirange类型

如下所示,在PG14之前,只能指定一个日期范围,而现在可以使用datamultirange函数指定多个日期范围

早期

代码语言:javascript复制
SELECT daterange(CURRENT_DATE, CURRENT_DATE   1);
       daterange
-------------------------
 [2021-07-27,2021-07-28)

PG14

代码语言:javascript复制
SELECT datemultirange( daterange(CURRENT_DATE    , CURRENT_DATE   2),
                       daterange(CURRENT_DATE   5, CURRENT_DATE   8));
                   datemultirange
---------------------------------------------------
{[2021-07-27,2021-07-29),[2021-08-01,2021-08-04)}

9) ECPG现在支持DECLARE STATEMENT结构

允许ECPG标识符链接到指定连接。当动态SQL语句使用这个标识符时,通过关联的连接来执行。通过DECALARE...STATEMENT完成:

代码语言:javascript复制
EXEC SQL BEGIN DECLARE SECTION;
 char dbname[128];
 char *dym_sql = "SELECT current_database()";
EXEC SQL END DECLARE SECTION;
代码语言:javascript复制
int main()
{
 EXEC SQL CONNECT TO postgres AS conn1;
 EXEC SQL CONNECT TO testdb   AS conn2;
 EXEC SQL AT conn1 DECLARE stmt STATEMENT;
 EXEC SQL PREPARE stmt FROM :dym_sql;
 EXEC SQL EXECUTE stmt INTO :dbname;
 printf("%sn", dbname);
 EXEC SQL DISCONNECT ALL;
 return 0;
}

上面的例子展示了用户如何声明一个简单语句:SELECT current_database(),然后定义连接到不同的database。从而,通过DECLARE语句,可以使用一个连接,执行连接上的语句。这对于想在不同连接上执行语句的应用来说非常有用。

数据损坏

PG现在提供一些工具,可以用来检测数据库是否损坏;还有一些小工具帮助用户修复损坏的数据。

1) amcheck模块提供函数允许检查heap页,之前仅能检测B-tree索引页

2) 添加了命令行工具pg_amcheck,简化在表上运行contrib/amcheck操作。有很多选项供选择检测哪个表、执行什么检查。可以并行执行检查

3) 添加了pg_surgery模块,该模块允许更改行可见信息。这对于纠正数据库损坏很有用。但如果使用不当,很容易损坏以前未损坏的数据库,进一步损坏数据库。需要强调的是,必须谨慎使用此工具,并只能由了解自己在做什么的用户使用。

索引

1) 可以通过预排序数据构建一些GiST索引

自动预排序,允许创建更快的索引和更小的索引。仅支持浮点类型。

2) BRIN索引现在可以记录每个范围的多个min/max值

如果每页都由一组值,这将很有用。允许更加有效地处理异常值。可以指定每个页面范围值的个数,要么是单点,要么是一个边界间隔:

代码语言:javascript复制
CREATE TABLE table_name (a int);
CREATE INDEX ON table_name USING brin (a int4_minmax_multi_ops(values_per_range=16));

3) BRIN索引现在可以使用bloom过滤。

允许BRIN索引高效使用在没有物理存储到heap中的数据。

4) SP-GiST可以使用INCLUDE列

允许对SP-GiST索引进行更多的仅索引扫描

5) REINDEX现在可以处理分区表的所有子表或索引

6) REINDEX现在可以改变新索引的表空间

通过指定TABLESPACE子句来完成。添加--tablespace选项到reindexdb中控制该行为

扩展统计

PG14下一个增强功能是扩展统计方面。帮助我们对使用表达式的各种查询获取更好的统计信息,帮助产生更好的查询计划。

1) 扩展统计现在在表达式中使用:

代码语言:javascript复制
CREATE TABLE table_name (a int);
CREATE STATISTICS statistics_name ON mod(a,10), mod(a,20) FROM table_name;
ANALYZE table_name;

采集的统计信息对带有WHERE或GROUP BY子句中,该子句使用表达式,进行评估非常有用:

代码语言:javascript复制
SELECT * FROM table_name WHERE mod(a,10) = 0 AND mod(a,20) = 0;
SELECT 1 FROM table_name GROUP BY mod(a,10), mod(a,20);

查询中使用表达式时,可以获得更好的查询计划。

2) 增加了可用于OR子句评估的扩展统计信息的位置数量。

VACUUM

Vacuum进行了增强:

1) 当可移动索引条目数量微不足道时,可以跳过索引清理,减少了vacuum时间

2) 如果表接近xid或者multixact回卷,vacuum操作更加激进

由vacuum_failsafe_age和vacuum_multixact_failsafe_age参数控制。Autovacuum开始很长时间后,这种机制总会触发以组织回卷。

3) 使用现有统计信息,可以加快有很多表的database的vacuum

Benchmark显示20000个表,10个autovacuum进程并发执行,可以将性能提高三倍以上。

4) Vacuum可以激进地将新删除的B-tree页添加到空闲空间映射表中,以便重用。

之前版本,vacuum只能将之前已存在的被删除的页添加到空闲空间映射表中。这个改进可以减少B-tree索引新页的空间分配,优化空间大小。

5) Vacuum可以回收位置有的heap line指针使用的空间

避免了某些负载的行指针膨胀,尤其时涉及在同一个表中进行持续范围删除和批量插入的操作

6) 在CREATE INDEX CONCURRENTLY和REINDEX CONCURRENTLY操作期间,vacuum可以积极地删除死记录。

PG14中的性能改进

该版本包含了一些可以提高性能的改进。

1) 多CPU和高会话计数的系统上计算MVCC可见性快照的速度得到改进:当有许多空闲会话时,这也可以提高性能。对于只读查询的大量连接,大约有2倍的增益。

2) 当只有少数分区受到影响时,分区表上的更新/删除性能得到改进:允许分区表上执行删除/更新时使用execution-time分区修剪;对于继承的UPDATE/DELETE,不是为每个目标关系生成单独的子计划,而是生成一个与SELECT计划完成相同的单个子计划,然后在其上添加ModifyTable。

3) 引用多个外部表的查询,现在可以并行执行外部表扫描:目前唯一可以同时运行的阶段类型是ForeignScan,他是Append的直接字节点;一个ForeignScan访问不同远程服务器上数据时,可以并行执行ForeignScan,重叠操作改进性能;如果设置了async_enable,postgres-fdw支持这种类型的扫描

4) LZ4压缩可以用于TOAST数据:可以在列级别设置或者通过default_toast_compression设置默认值。服务必须--with-lz4编译。默认仍是PGLZ;LZ4的压缩性能比PGLZ更好,使用更少CPU。测试表明,性能可以提升2倍以上,空间大小仅比PGLZ稍大。我建议在使用任何一种方法之前使用生产数据对此进行测试;Haiying Tang 描述了如何使用这个选项,参考:

https://mp.weixin.qq.com/s?__biz=MzU1OTgxMjA4OA==&mid=2247484439&idx=1&sn=0aba55afbcba7f2c19ae3b01575b490b&chksm=fc10d880cb675196ff069650e2840ef1de147b78110b46b8fb53b6dd481b1887ca3bc1fb3c68&token=642725105&lang=zh_CN#rd

5) 添加的B-tree索引可以删除过期的索引条目,以防页分裂:帮助减小频繁更新索引列的造成的索引膨胀;当怀疑连续update带来的版本流失造成重复项出现时,该机制会试图删除重复项。

6) libpq中改进了pipeline模式:允许发送多个查询,并仅当发送了指定的同步消息时等待完成;它增加了客户端应用程序的复杂性,并且需要格外小心以防止客户端/服务器死锁,但管道模式可以提供相当大的性能改进,以换取内存使用量的增加,从而使状态保持更长时间;管道模式在服务器距离较远时最有用,即当网络延迟ping 时间较长时,以及许多小操作正在快速连续执行时。

7) Executor方法添加到了nextloop join的inner表缓冲结果中:如果在inner检查一小部分行时很有用,由enable_memorize控制;当查找的不同值较少且每个值的查找次数较大时,使用带有结果缓存的参数化嵌套循环的好处会增加

8) FDW API 和 postgres_fdw 已扩展为允许批量插入外部表:如果FDW支持批量,并且请求了批量,那么累积行并以批量形式插入,否则每次插入一行;由于到外部服务器的每次往返都有很高的延迟,因此批处理通常比插入单个行更有效

9) 改进了带有表达式IN(const-1,const-2,等)子句的查询性能:通过hash表查询替换当前顺序查询达到改进性能的目的

10) 改进了在具有大量共享缓冲区的集群上恢复期间对小表执行 CREATE TABLE 操作的截断、删除或中止性能。在许多情况下,当几个小表(用 1,000 个关系测试)被截断,并且服务器配置有大量共享缓冲区(大于等于 100 GB)时,这将性能提高了 100 倍以上

11) 改进了恢复、备机回放、大量更新的vacuum的性能:性能提升来自于压缩页面的算法优化,我们需要在大更新后使用它

12) 改进了并行顺序扫描的 I/O 性能:以组的形式将块分配给并发进程,从而提升性能。

详情参考:

https://www.postgresql.org/docs/release/14.0/

PG15及更高版本

最后列出PG社区正讨论的特性,可能加入到PG15或之后的版本中。以下功能仅是个人观点,不保证最后是否会实现并合入未来版本。

1) 逻辑复制的各种改进

在订阅者端支持2PC;schema的发布;允许解决冲突的选项或工具;sequence的复制;行级别的过滤器使数据分片更加便利;列级别的过滤;不发送空事务,提高网络带宽;备机开启逻辑复制

2) 备份技术中服务端进行压缩

3) 自动switchover/failover的改进

4) hash索引的改进:允许唯一索引、允许多列索引

5) 共享内存的统计采集:更加可靠,无需通过UDP协议进行通信;减少读、写,提高性能

6) 并行写:并行insert、并行COPY FROM...、并行查询性能改进

7) 异步IO:允许预取数据并提高系统的速度

8) DIRECT IO:绕过操作系统缓冲,在某些情况下带来更好性能

9) 通过FDW的2PC:为了进一步推进基于PG的分配解决方案

10) 通过使用性能数据结构改进VACUUM

11) 全局临时表:临时表更加方便管理,迁移更加便利

12) 物化视图的增量维护

13) 事务ID的64位实现

...

原文

https://www.postgresql.fastware.com/blog/postgresql-14-and-beyond

0 人点赞