阿里巴巴编程之夏(ASoC)是面向全球18岁及以上本科、硕士、博士高校学生的技术普惠计划,它旨在鼓励高校学生深度参与开源开发活动,激励学生以第一视角感受开源世界的魅力。ASoC 以阿里巴巴开源技术力量作为媒介,为高校学生们和开源社区搭建桥梁。阿里巴巴编程之夏(ASoC)2022届已经结束,有60位同学成功结业,ASoC2022经验分享系列文章将持续给大家分享结业同学的经验和感悟。
PolarDB是阿里巴巴自研的新一代云原生关系型数据库,在存储计算分离架构下,为用户提供具备极致弹性、高性能、海量存储、安全可靠的数据库服务。PolarDB for PostgreSQL 采用了基于 Shared-Storage 的存储计算分离架构。数据库由传统的 Share-Nothing 架构,转变成了 Shared-Storage 架构——由原来的 N 份计算 + N 份存储,转变成了 N 份计算 + 1 份存储;PolarDB for PostgreSQL引擎基于PolarDB架构,100%兼容PostgreSQL 11。而 PostgreSQL 使用了传统的单体数据库架构,存储和计算耦合在一起。

2.项目介绍
原有PostgreSQL不具备分布式处理COPY语句的功能。本项目将利用PolarDB for PG 的 HTAP 框架,对 COPY 命令来进行加速。
该项目的分为以下四个子目标进行实现
- COPY relation TO file,COPY (query) TO file,读取操作可以实现多机(多个只读结点)并行读取
- COPY relation FROM file可以在单个读写结点上,利用多进程来并行写入csv文件
- 用一个开关使用户可以随时打开或关闭这个功能
- 根据性能提升结果完成一个性能测试报告。
3.开发情况
开全局控制开关
px_enable_copy将用来设置是否开启copy分布式加速,但是只有在polar_enable_px同时开启才可生效。主要修改文件为src/backend/utils/misc/guc_px.c:
bool px_enable_copy;
{
{"polar_px_enable_copy", PGC_USERSET, QUERY_TUNING_METHOD,
gettext_noop("Enable px_enable_copy."),
NULL
},
&px_enable_copy,
false,
NULL, NULL, NULL
},用户可以通过如下命令打开,SQL set polar_px_enable_copy=on;
COPY query To…
原有PolarDB for PG中,Copy query To ...中的 query 无法生成PX计划。
需要将 CURSOR_OPT_PARALLEL_OK (src/backend/commands/copy.c:1532) (代表使用原生优化器) 修改为 CURSOR_OPT_PX_OK(代表使用 PX 优化器)。
即要进行如下的修改:
修改后结果如下
/* 修改前 */
plan = pg_plan_query(query, CURSOR_OPT_PARALLEL_OK, NULL);
/* 修改后 */
plan = pg_plan_query(query, CURSOR_OPT_PX_OK, NULL);
COPY ... To ...
因为 PolarDB 采用的 shared-everything 存储方式,所以每一个只读节点(PX)都可以读取数据。但是只有一个读写节点(QC)可以进行写操作。读写节点将COPY ... To ...命令分发给各个只读节点,而只读节点生成对应的worker执行操作。操作流程如下图所示,

实现这个流程主要由四个函数实现,分别为makepxCopy,pxCopyStart,pxCopyGetData和pxCopyEnd。四个函数之间的执行流程如下图所示,

读写节点进行分发之前在进行的COPY语句的信息,makepxCopy函数的作用就是完成这个操作。PxCopy将用于命令分配,因此在makepxCopy中,采用需要POLICYTYPE_REPLICATED对PxCopy进行初始化。在PolarDB中,每个只读节点都以为读取所有数据,所有我们只选取一个replica进行分发,防止重复发送。
pxCopyStart中,只读节点将分配一个writer gang来分发命令。收到命令的只读节点开始执行,而读写节点将不断执行pxCopyGetData直到分发的命令都完成。最后由pxCopyEnd处理各个进程的收尾工作。
COPY ... From ...
因为PolarDB只用一个读写节点,对于COPY ... From ...语句,我们不可以使用多个只读节点并行写入,而需要使用读写节点下的子进程,即PX worker,进行并发写入。操作流程如下图所示,

实现这个流程也是由四个函数实现,分别为makepxCopy,pxCopyStart,pxCopySendData和pxCopyEnd。四个函数之间的执行流程如下图所示,

在makepxCopy中,不在只用一个relica,而是为每一个segment分配一个读写进程(RW_SEGMENT)。然后pxCopySendData中,读写进程处理每行结果进行写入。
性能分析
在完成上述工作后,我有对COPY语句进行了性能测试。对于COPY query To ...,并行度提升为2时,性能有明显的上升。但是当我增加每个并行节点中的PX worker,并行度提升后,性能并没有呈现出预期的增长。

对于COPY ... To ...,同样呈现出相同的结果。

经过排查,我发现性能的瓶颈不在于只读节点的并行上,而是读写节点的写入速度上。尽管我们可以不断压缩读入时间,但是只有一个读写节点,写入速度被限制。
3.体验与收获
Q:简单自我介绍一下吧
我叫黄伟鋆,目前是丹麦科技大学(Technical University of Denmark)的研二学生,对数据库比较感兴趣。这是我第一次参加阿里巴巴开源之夏的活动,很高兴能在这个暑假参与其中,并在这里分享我的一些经验。
Q:这是你第一次参加类似编程之夏的暑期开源活动吗?是从什么渠道知道该活动的呢?
其实我接触开源这个概念比较早,但是实实在在地参与到开源项目的开发是这两年的事情。在阿里巴巴编程之夏期间,我对数据库存储有了更深层次地理解。而且也对未来继续参加相关活动,参与开源项目充满期待。
Q:今年编程之夏2022开源项目开发过程中遇到的最大的挑战是什么?如何解决的?
在参与阿里巴巴开源之夏的这两个月里,我深刻地感受到,编程开发操作需要以理论知识为基础,同时结合结合起实际操作加深理解。在项目刚开始时,我对COPY的分布式加速只是有个粗浅的理解。但是和何柯文导师的讨论中,我加深了对PolarDB的理解,发现了性能瓶颈与一些解决方案,最后顺利完成了项目要求。这个过程中,我对数据库,对分布式存储的理解又再次加深了。
Q:有什么要跟其他学弟、学妹们说的吗?
对于从未接触开源的朋友来说,参与到实际开源项目的开发好像时间很遥不可及的事。其实每个人都可以为开源项目贡献自己一份力。一开始我们可以从为项目文本找typo来熟悉Git的操作,再到后来可以通过解决一些 good first issue 来熟悉项目,最后不断地为项目贡献,挑战新的任务。相信大家这个过程中,不知不觉就能学到许多。




