PostgreSQL 11 正式版发布
2018-10-19 14:34:35 阿炯

PostgreSQL第11版正式发布了,它带来了整体性能的改进,具有与超大型数据库和高计算工作负载相关的特定增强功能。此外对表分区系统进行了重大改进,存储过程中支持事务,改进了查询并行性能并增加了并行化数据定义功能,同时在查询中引入了 JIT 编译以加速表达式的执行。主要更新内容如下:

提高分区的健壮性和性能

增加了通过 hash key 对数据进行分区的能力,增强了当前通过值列表或范围对 PostgreSQL 中的数据进行分区的能力。进一步提高了其数据联合能力,并对使用 PostgreSQL 外部数据包装器 postgres_fdw 的分区进行了功能改进。为了帮助管理分区,为与分区键不匹配的数据引入了一个默认分区,并且能够在传递给所有分区的分区表上创建主键、外键、索引和触发器。如果更新行的分区键, 还支持自动将该行移动到正确的分区。通过使用新的分区消除策略提高了从分区读取时的查询性能。此外,现在支持分区表上流行的“upsert”功能,这有助于简化用户与数据交互时程序的代码并减少网络开销。

存储过程中支持事务

在 PostgreSQL 11 之前,用户定义的函数无法管理自己的事务,在第11版本中添加了可以在函数体内执行完整事务管理的 SQL 过程,使开发人员能够创建更高级的服务器端应用程序,例如涉及增量批量数据加载的应用程序。

查询并行性能提升

提高了并行查询性能,同时并行顺序扫描和散列连接的性能得到提升,对分区数据的扫描也更高效。如果底层查询无法并行化,PostgreSQL 现在可以执行并行使用 UNION 的 SELECT 查询。此处请参考:PostgreSQL 11 preview - parallel hash(含hash JOIN , hash agg等)性能极大提升

表达式 JIT 编译

引入了对 JIT 编译的支持,以加速查询执行期间某些表达式的执行。PostgreSQL 的 JIT 表达式编译使用 LLVM 项目来加速 WHERE 子句、目标列表、聚合、映射和一些内部操作中表达式的执行。此外还有一些更新关注于改进用户体验,详情查看发行公告,下面将详述。

分区表的改进
对分区表进行了重大的改进,例如增加了哈希分区、支持创建主键、外键、索引、支持UPDATE分区键以及增加了默认分区,这些功能的完善极大的增强了分区表的可用性,详见以下:
PostgreSQL11:分区表增加哈希分区
PostgreSQL11:分区表支持创建主键、外键、索引
PostgreSQL11:分区表支持UPDATE分区键
PostgreSQL11:分区表增加 Default Partition

支持存储过程
第11版本一个重量级新特性是对存储过程的支持,同时支持存储过程嵌入事务,存储过程是很多 PostgreSQL 从业者期待已久的特性,尤其是很多从Oracle转到PostgreSQL朋友。尽管PostgreSQL提供函数可以实现大多数存储过程的功能,但函数不支持部分提交,换言之,函数中的SQL要么都执行成功,要不全部返回失败,详见以下:
PostgreSQL11:支持存储过程(SQL Stored Procedures)

并行能力的增强
第11版本在并行方面得到较大增强,例如支持并行创建索引、并行Hash Join、并行 CREATE TABLE .. AS等,详见以下:
PostgreSQL11:支持并行创建索引(Parallel Index Builds)
PostgreSQL11:支持并行哈希连接(Parallel Hash Joins)

增加对Just-in-Time (JIT)编译的支持
一个重量级新特性是引入了 JIT (Just-in-Time) 编译来加速SQL中的表达式计算效率。JIT 表达式的编译使用LLVM项目编译器来提升在WHERE条件、指定列表、聚合以及一些内部操作表达式的编译执行,详见以下:
PostgreSQL11: 增加对JIT(just-in-time)编译的支持提升分析型SQL执行效率

其它功能完善
此外还增强了其它新特性以增加用户体验,以下列举了主要的几点,详见以下:
PostgreSQL11: 新增非空默认值字段不需要重写表
PostgreSQL11: Indexs With Include Columns
PostgreSQL11: 新增三个默认角色
PostgreSQL11: 可通过GRNAT权限下放的四个系统函数
PostgreSQL11: Initdb/Pg_resetwal支持修改WAL文件大小
PostgreSQL11: psql 新增 gdesc 显示查询结果的列名和类型
PostgreSQL11: psql 新增变量记录SQL语句的执行情况和错误


2018 年 10 月 18 日 PostgreSQL 发布了第11版本,该版本的主要特性如下:
提升分区功能
    支持 HASH 分区,目前已经支持 RANGE,LIST 和 HASH 三种分区方式
    分区表支持主键,外键, 索引和触发器
    为不符合任何分区的数据提供 default 分区
    UPDATE 分区键可以将其移动至合适的分区
    在计划和执行阶段,增强分区裁剪策略,提升 SELECT 性能

提升并行能力
    并行创建 B-tree 索引
    CREATE TABLE ... AS, CREATE MATERIALIZED VIEW 和特定的 UNION 查询支持并行
    优化并行 HASH JOIN 和 并行顺序扫描

存储过程中支持嵌入事务
可选的 Just-in-Time (JIT) 编译选项,提升表达式计算性能
支持 SQL:2011 标准中窗口函数对应的所有 window frame 选项
覆盖索引可以使用 INCLUDE 子句包含其他的非索引字段

从分区表和并能能力的增强可以看出,PostgreSQL 11 对于大数据量下的数据管理和查询能力都在提升,在存储空间不成为瓶颈的情况下,PostgreSQL 正努力将单机性能发挥到极致。

分区表

分区与 sharding
PostgreSQL 的分区与为解决传统数据库系统扩展问题的 sharding 方案是很相似的,区别在于前者将一张逻辑表划分为多个物理表存储在当前实例上,后者将多个物理表分布在不同的实例上;两者均通过水平切分将大表拆成小表,通过该方法,前者突破单表的大小限制,后者突破单实例的大小限制。其实借助 PostgreSQL 的分区能力以及 postgres_fdw 能力,完全可以将分区表中不同的分区存储在不同的外部表中,这些外部表可以是 PostgreSQL,也可以是 MySQL,甚至其他数据库类型。不妨来看一下在 PostgreSQL 中创建外部表的语法:
CREATE FOREIGN TABLE foreign_table (
 id integer NOT NULL,
 data text
)
SERVER foreign_server OPTIONS (schema_name 'some_schema', table_name 'some_table');

以上语法如果可以支持指定多个 SERVER,建表语句支持 PARTITION BY,是否就实现了跨多实例的 sharding 方案呢?其实目前是支持手动配置外部分区表的,只是使用起来会比较繁琐,另外 pg_shardman 也做了同样的事情,如果 PostgreSQL 能从语法上直接支持使用起来就方便多了。关于 PostgreSQL 内置 sharding 的信息可以参考这个Wiki。另外分区表已经支持了默认分区,离支持自动扩展分区还远么?参考 Oracle 的 interval partition

PostgreSQL 11 的一个重量级新特性为分区表得到较大增强,例如支持哈希分区(HASH)表,因此 PostgreSQL 支持范围分区(RANGE)、列表分区(LIST)、哈希分区(HASH)三种分区方式。

Hash Partitioning
The table is partitioned by specifying a modulus and a remainder for each partition. Each partition will hold the rows for which the hash value of the partition key divided by the specified modulus will produce the specified remainder.

Hash分区表的分区定义包含两个属性,如下:
modulus: 指Hash分区个数。
remainder: 指Hash分区键取模余。

创建分区表语法

CREATE TABLE table_name (  ...  )
[ PARTITION BY { RANGE | LIST | HASH }  (  { column_name |  ( expression )  }
 CREATE TABLE table_name
PARTITION OF parent_table [  (
)  ] FOR VALUES partition_bound_spec


统计各分区表中的数据量情况
SELECT tableoid::regclass,count(*) from sysdskptrn group by 1 order by 1;

根据分区键字段查询仅扫描对应的分区表,并走了索引;对非分区键进行查询会扫描分区表所有分区。第11分区表的一些新的特性实现了第10版本中无法实现的一些功能,盘点如下:

1、UPDATE操作可以跨分区移动行
PostgreSQL 10不允许执行可能导致更新结束时行会移动到其他不同分区的更新。但是在PostgreSQL 11中是可以这样操作的。

2、创建默认分区
在PostgreSQL11中,可以创建一个“默认”分区,它可以存储不属于任何现有分区范围或列表的行。
# create table mytable_default partition of mytable default;

使用默认分区可以插入不属于任何现有分区范围/列表的行。解绑Default分区:
=> ALTER TABLE mytable DETACH PARTITION mytable_default;

对于添加了DEFAULT分区的分区表如果想增加分区,需参照“解绑DEFAULT分区,创建新分区,转移分区数据,连接DEFAULT分区”的步骤进行。

3、自动创建索引
在PostgreSQL 10中,必须为每个分区手动创建索引,尝试在父表上创建分区会失败。在PostgreSQL 11中,如果在父表上创建索引,Postgres将自动在所有子表上创建索引,创建索引后创建的任何新分区也将自动获取添加到其中的索引。

4、外键支持
在PostgreSQL 10中,分区表中的列不可能是外键。但是在PostgreSQL 11中,是支持外键的,子表上也自动创建了外键。

5、唯一索引
在PostgreSQL 10中,必须在子表中强制执行唯一约束,无法在主表上创建唯一索引。在PostgreSQL 11中,是可以在主表上创建唯一索引的。

6、分区级别的聚合
PostgreSQL 11附带了一个名为enable_partitionwise_aggregate的新选项,可以打开该选项以使查询计划程序将聚合推送到分区级别。 默认情况下,此选项已关闭。

可打开该选项:set enable_partitionswise_aggregate=on;

7、Hash分区
在PostgreSQL11中,加入了HASH类型的分区。 散列类型分区根据分区键的散列值分配行。


分区表与性能
借助分区表和 postgres_fdw 可以实现表存储空间的扩展,但如果单机性能达到瓶颈,大数据量下的复杂查询依然很难满足企业用户 OLAP 的场景。因此,PostgreSQL 在性能方面做了很多努力。

并行 JOIN
两个分区表 JOIN,如果满足分区方式相同,分区数量相同,并且 JOIN 条件是分区键的等值连接等条件,则可以对每个分区分别做 JOIN,然后 UNION(对应计划树节点为 APPEND) 在一起,而每个分区的 JOIN 是可以并行执行的。可以参考德哥的分区表智能并行JOIN,性能提升约 2.4 倍。


并行聚合
与并行 JOIN 类似,在每个分区上分别做局部聚合(可并行),最后再做一次整体聚合,可以参考德哥的分区表智能并行聚合、分组计算

postgres_fdw 和 下推
分区表和外部表下推优化有所增强,可以将更多的操作下推至外部表执行:
INSERT, UPDATE, 和 COPY 操作可以下推至外部表执行。
有 JOIN 的 UPDATE 和 DELETE 可以下推至外部表执行,之前仅能下推没有 JOIN 的 UPDATE 和 DELETE。
可以下推聚合操作至外部表执行。

性能增强
性能增强方面,除以上提到的下推优化之外,在并行方面也做了增强:
部分 DDL 支持并行,如创建索引,CREATE TABLE .. AS, SELECT INTO, and CREATE MATERIALIZED VIEW,并行排序和排序可以参考德哥并行排序、索引的测试文章。
允许 LIMIT 传递到 Parallel worker 上执行,进而减少返回的行数。
HASH JOIN 支持共享哈希表,之前每个 Parallel worker 有自己的一个哈希表副本。

值得一提的是,PostgreSQL 11 中增加了对 JIT 的支持,目前仅支持表达式计算,对于有复杂表达式计算的 OLAP 场景应该会有不小的性能提升。

用户体验
用户体验方面,有一些比较有意思的点:psql 可以使用 exit 和 quit 退出了,有多少用户第一次使用 psql 时不知道如何退出?与 MySQL 相比,PostgreSQL 还有很多命令不是很直观的,这个后续可以整理下常用命令的对应关系。执行 ALTER TABLE .. ADD COLUMN .. DEFAULT .. 使用常量(非 NULL)作为默认值时,不用在执行的时候重写整张表了,具体实现方法待学习验证。

本文简单记录 PostgreSQL 11 中比较受大众关注的方面。总体来讲,PostgreSQL 在分区表的支持和性能的提升上都给人很大的惊喜,非常期待 PostgreSQL 在 HTAP 场景中的应用实现机制。PostgreSQL 最新的 feature 和 patch 可以在 commitfest 和 git 上查看,也可以订阅邮件列表来了解社区同仁的动态或者提出问题;更多的咨询可以到官网查阅。更多第11版的特性可以参考官网 发行说明 和德哥的 PostgreSQL 11 preview 系列文章,或中文官方手册《PostgreSQL 11.2 手册》。


该文章最后由 阿炯 于 2022-08-14 21:22:58 更新,目前是第 2 版。