百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

大分区表高并发性能提升100倍?阿里云 RDS PostgreSQL 12 解读

toyiye 2024-09-14 13:35 5 浏览 0 评论

作者:凌策世界上几乎最强大的开源数据库系统 PostgreSQL,于 2019 年 10 月 3 日发布了 12 版本,该版本已经在阿里云正式发布。PostgreSQL 12 在功能和性能上都有很大提升,如大分区表高并发性能提升百倍,B-tree 索引空间和性能优化,实现 SQL 2016 标准的 JSON 特性,支持多列 MCV(Most-Common-Value)统计,内联 CTE(Common table expressions)以及可插拔的表存储访问接口等。本文对部分特性进行解读。

分区表性能

PostgreSQL 对分区表的支持由来已久。在 10.0 之前,分区表需要用户通过继承的方式手动创建,从 10.0 开始支持声明式分区,即通过 SQL 直接创建分区表,改善了分区表的易用性;在 11 中,支持 HASH 分区,并在计划和执行阶段,增强分区裁剪策略,提升分区表查询性能;PostgreSQL 12 进一步增强了分区表的查询和数据导入性能,尤其对分区数量多的场景,查询优化效果尤为显著。

在阿里云创建两个同等规格(4c8g)的 RDS PostgreSQL 11 和 12 的实例,测试不同分区数情况下,使用 COPY 导入 1 亿行数据的性能对比如下。可见,随着分区数增多,导入性能始终优于 PostgreSQL 11。COPY 导入数据的性能提升得益于在 12 中支持了分区表批量插入,在次之前,仅支持一次一行的插入模式。

对于查询操作,在 PostgreSQL 10 中,会依次检查每个分区表,判断其可能有满足条件的数据,每个分区表的处理与普通表的处理流程类似;PostgreSQL 11 引入了分区裁剪特性,可以更早地定位需要访问的分区;PostgreSQL 12 则近一步将分区裁剪功能前置,避免为每个分区加载元数据并生成相应的内部结构,使得查询计划耗时进一步与无关的分区解耦。由此可见,该优化与查询条件的分区过滤性相关,分区过滤性越好,所需处理的分区越少,优化效果越好。

不同分区数下,分区键(同时也是主键)上的查询性能对比如下。可见,分区数越多,PostgreSQL 12 的性能提升越明显,最高提升达 150 倍。而随着分区数增加,PostgreSQL 12 的性能则保持相对稳定。

虽然分区表性能有大幅提升,但与单表相比,在很多场景下性能还有一定差距,在做表结构设计时,仍然需要结合实际业务场景,选择是否分区以及分区数量。

索引增强

B-tree 索引被广泛应用于数据库系统中,可以有效减少查询需要访问的数据量,提升查询性能。索引是一种 "空间换时间" 的查询优化策略,本身也会占用一些存储空间,其性能对查询也至关重要。PostgreSQL 12 提升了标准 B-tree 的整体性能,减少了磁盘空间占用,对于复合索引,其空间使用率最多可减少 40%,可以有效节省用户的磁盘空间;对于有重复项的 B-tree 索引,其性能也有所提升。另外,引入 REINDEX CONCURRENTLY 命令,用户可以在业务无感知的情况下重建索引。

我们通过测试直观感受一下 B-tree 索引的空间占用优化。分别在 PostgreSQL 11 和 12 中创建如下表和索引,并插入 2000 万行数据,VACUUM 更新统计信息。

CREATE TABLE foo (
    aid bigint NOT NULL,
    bid bigint NOT NULL
);
ALTER TABLE foo
    ADD CONSTRAINT foo_pkey PRIMARY KEY (aid, bid);
CREATE INDEX foo_bid_idx ON foo(bid);
INSERT INTO foo (aid, bid)
    SELECT i, i / 10000
    FROM generate_series(1, 20000000) AS i; 
VACUUM (ANALYZE) foo;  

分别查看两个 PostgreSQL 版本中 foo_bid_idx 索引的大小,如下:

  #  PostgreSQL 11
postgres=> \di+ foo_bid_idx
                                    List of relations
 Schema |    Name     | Type  |    Owner    | Table | Persistence |  Size  | Description
--------+-------------+-------+-------------+-------+-------------+--------+-------------
 public | foo_bid_idx | index |   postgres  | foo   | permanent   | 544 MB |
(1 row)
2 .# PostgreSQL 12
postgres=> \di+ foo_bid_idx
                                    List of relations
 Schema |    Name     | Type  |    Owner    | Table | Persistence |  Size  | Description
--------+-------------+-------+-------------+-------+-------------+--------+-------------
 public | foo_bid_idx | index |   postgres  | foo   | permanent   | 408 MB |
(1 row)  

可见,PostgreSQL 11 的索引比 PostgreSQL 12 大 33%,在索引较多的场景下,如此大幅度的空间节省还是很可观的。

除 B-tree 索引外,其他索引也有增强。如减小生成 GiST、GIN 和 SP-GiST 索引的WAL日志的开销,支持用 GiST 创建覆盖索引,支持用 SP-GiST 索引的 distance 运算符执行 K-NN 查询等。

支持 SQL/JSON 路径语言(path language)

PostgreSQL 在之前的版本中就已经支持了 JSON 数据类型,并支持对简单 JSON 数据的查询操作,如果 JSON 数据比较复杂,如嵌套较多,包含数组等,则不能便捷地查询其中的值,往往需要依赖外部插件来实现,比如支持 SQL/JSON 路径语言 的 jsquery 插件。

PostgreSQL 12 对非结构化数据的支持再进一步。内置支持了 SQL 2016 标准引入的 JSON 特性和丰富的路径查询方法,引入新的数据类型 jsonpath 表示路径表达式(path expression),支持 JSON 上的各种复杂查询,不再依赖插件。具体的使用方法可以参考文档,在此不赘述。

参数控制 Prepared 计划

对于重复执行的 PREPARE 语句,PostgreSQL 会缓存其执行计划,执行 PREPARE 语句时,PostgreSQL 会自动选择是重新生成一个新的计划(通常称之为定制计划,custom plan),还是使用缓存的计划(即通用计划,generic plan),但在特定场景下,数据库的选择可能并不是最优的。PostgreSQL 12 为用户提供了一个参数 plan_cache_mode 来自主选择使用哪种计划,比如查询的参数如果总是固定的常量,则可以显式设置该参数,使优化器总是使用通用计划,避免 SQL 解析和重写的代价,从而优化查询性能。

执行** PREPARE **并运行,前 5 次均使用定制计划:
postgres=> prepare p(integer) as select aid from foo where aid=$1;
PREPARE
postgres=> EXPLAIN EXECUTE p(1);
                               QUERY PLAN------------------------------------------------------------------------
 Index Only Scan using foo_pkey on foo  (cost=0.44..1.56 rows=1 width=8)
   Index Cond: (aid = 1)
(2 rows)
1.# 后续四次执行的结果在此省略  

执行第 6 次时使用通用计划,如下:
> postgres=> EXPLAIN EXECUTE p(1);
                               QUERY PLAN
-------------------------------------------------------------------------
 Index Only Scan using foo_pkey on foo  (cost=0.44..1.56 rows=1 width=8)
   Index Cond: (aid = $1)
(2 rows)  

重新执行 > PREPARE  
,并设置 > plan_cache_mode  
 为 > force_generic_plan  
,观察计划使用情况,可见第 1 次执行时就会使用通用计划,而无需等到第 6 次执行。
> postgres=> DEALLOCATE p;
DEALLOCATE
postgres=> prepare p(integer) as select aid from foo where aid=$1;
PREPARE
(1) # plan_cache_mode 设置为 force_generic_plan
postgres=> set plan_cache_mode = force_generic_plan;
SET
postgres=> EXPLAIN EXECUTE p(1);
                               QUERY PLAN
-------------------------------------------------------------------------
 Index Only Scan using foo_pkey on foo  (cost=0.44..1.56 rows=1 width=8)
   Index Cond: (aid = $1)
(2 rows)  

是否使用通用计划可以通过执行计划中变量是否做了参数化处理来判断。

可插拔表存储接口

一直以来,PosgreSQL 都只支持 heap 表这一种存储引擎,其实现与其他模块耦合较多。PostgreSQL 12 借鉴自身索引可扩展的实现方式,抽象出一层存储引擎访问接口,为后续支持多种存储引擎奠定了基础,如 ZHeap、列存、K/V 存储、内存引擎等。

可插拔表存储访问接口的架构如下,在原有架构基础上,增加了 表访问管理层(Table Access Manager),提供统一的表访问接口,不同的存储引擎只需实现该接口即可接入。

目前,存储引擎仍然只支持 Heap 表,相信不久的将来会支持更多的存储引擎。感兴趣的读者也可以尝试自行实现一个存储引擎。

postgres=> select * from pg_am;
 oid  | amname |      amhandler       | amtype
------+--------+----------------------+--------
    2 | heap   | heap_tableam_handler | t
  403 | btree  | bthandler            | i
  405 | hash   | hashhandler          | i
  783 | gist   | gisthandler          | i
 2742 | gin    | ginhandler           | i
 4000 | spgist | spghandler           | i
 3580 | brin   | brinhandler          | i
(7 rows)  

丰富的插件支持

阿里云 RDS PostgreSQL 12 提供了更加丰富的插件支持,满足广大用户在一些垂直领域和特殊场景下的需求,以下介绍一些较常用、有趣的插件,更多支持插件可以参考 PostgreSQL 的支持插件列表。

? roaringbitmap 将 roaringbitmap 作为一种内置数据类型,提供丰富的函数支持,使用 Roaring Bitmap 算法,极大提升位图计算性能。

? RDKit 支持 mol 数据类型(描述分子类型)和 fp 数据类型(描述分子指纹),支持化学分子计算和化学分子检索等功能。

? Ganos 阿里云自研时空数据引擎,支持对空间/时间数据进行高效的存储、索引、查询和分析计算。

? PASE 高性能向量检索插件,使用业界成熟稳定且高效的 ANN(Approximate nearest neighbor)检索算法,包括 IVFFlat 和HNSW 算法,通过这两种算法,可以在 PostgreSQL 数据库中实现极高速向量查询。

? zhparser 中文分词插件,助力实现中文的全文检索。

? oss_fdw 使用该插件可以将 OSS 中的数据加载到 PostgreSQL 中,也支持将 PostgreSQL 中的数据写入 OSS 中。

总结

RDS PostgreSQL 12 无论功能和性能都有很大提升,包括分区表查询性能优化,B-tree 索引空间优化和性能提升,参数方式选择 Prepare 语句执行计划,内置的、功能全面的 SQL/JSON 路径语言和更加丰富的插件支持。可插拔表访问接口作为未来支持多存储引擎的基础,意义重大,目前仍然只支持 Heap 表,用户测暂时不会有感知。除本文介绍的特性外,该版本还有很多其他特性,如多列 MCV(Most-Common-Value)统计,内联 CTE(Common table expressions)等,文中未及介绍,感兴趣的读者可以参考相关文献或者在阿里云购买实例进行体验

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码