Apache Cloudberry™ (Incubating) 是 Apache 软件基金会孵化项目,由 Greenplum 和 PostgreSQL 衍生而来,作为领先的开源 MPP 数据库,可用于建设企业级数据仓库,并适用于大规模分析和 AI/ML 工作负载。
GitHub: https://github.com/apache/cloudberry
在数据仓库与大数据分析领域,Greenplum Database 一直是开源 MPP(大规模并行处理)数据库的重要代表。然而,自从 Greenplum 走向闭源后,用户在版本升级、Bug 修复以及功能扩展等方面逐渐受到了限制。正是在这样的背景下,Apache Cloudberry 应运而生。
作为 Greenplum 的开源衍生版,Apache Cloudberry 完全兼容 Greenplum 的架构与语法,同时在功能、性能与安全性上进行了全面升级,成为当前最具潜力的 Greenplum 开源替代方案之一。
本文将详细介绍 cbcopy 的功能、机制与实战操作,并以一个完整案例演示如何快速完成从 Greenplum 迁移到 Apache Cloudberry 。
cbcopy 介绍
cbcopy 是一个数据迁移工具,可以在不同数据库集群之间传输数据,可以将一个 Greenplum 数据库集群中的元数据和数据快速复制到 Apache Cloudberry 数据库集群中。cbcopy 可以迁移数据库的全部内容,包括数据库架构、表数据、索引、视图、角色、用户自定义函数、资源队列、资源组等。
支持四种级别数据库对象迁移:
集群迁移:将源集群完整迁移到目标集群 数据库迁移:将源集群中指定数据库完整迁移到另外目标集群 模式迁移:将源集群的指定数据库下的指定模式(schema)迁移到目标集群指定数据库中 表迁移:将源集群的指定表迁移到目标集群
支持不同规模数据库集群迁移:
源集群计算节点(segment) 等于 目标集群计算节点(segment) 源集群计算节点(segment) 少于 目标集群计算节点(segment) 源集群计算节点(segment) 多于 目标集群计算节点(segment)
cbcopy 机制
cbcopy 是基于 copy on segment to program 和外部表功能实现,通过传输压缩降低数据迁移对网络资源使用、迁移数据校验保证数据一致。根据表数据量大小采用了两种不同的数据迁移策略来提高数据库集群迁移效率。
数据量小的表(默认低于 1000000):源集群管理节点连接目标集群管理节点,进行数据传输; 数据量大的表(默认高于 1000000):源集群计算节点(segment) 和目标集群计算节点(segment)上启动 helper 进程,helper 进程建立连接并传输数据。
cbcopy 实践
使用 cbcopy 工具将测试环境中 Greenplum 6 的数据库集群中的数据迁移到 Apache Cloudberry 集群。
测试环境
源 Greenplum 集群
目标 Apache Cloudberry 集群
测试数据
Greenplum 6 集群中 warehouse 数据库中生成了银行经典数仓的拉链测试数据。
迁移准备
检查 Greenplum 6 集群节点中是否存在/usr/local/greenplum-db/bin/gpcopy_helper 文件, 如果不存在将 Apache Cloudberry 集群节点上的 cbcopy_helper 文件拷贝到 Greenplum6 集群中,操作如下:
Apache Cloudberry集群coordinator节点(192.168.194.137):su - rootscp usr/local/cloudberry-db/bin/cbcopy_helper 192.168.194.55:/usr/local/greenplum-db/bin/GreenPlum 6 Master节点(192.168.194.55)同步到集群所有节点:su - rootsource /usr/local/greenplum-db/greenplum_path.shcd /usr/local/greenplum-db/bingpscp -f /home/gpadmin/hostfile_all cbcopy_helper =:$PWD/
数据迁移
在 Apache Cloudberry 集群的 coordinator 节点上运行 cbcopy 命令进行数据迁移,可以将整个集群或者指定的 database 快速从 Greenplum 迁移到 Apache Cloudberry。迁移的日志保存在 cbcopy 执行节点的/home/gpadmin/gpAdminLogs 目录下。
整个集群迁移
将 Greenplum 6 集群中的所有 database(测试环境中创建了 dw、warehouse 两个数据库)全部迁移到 Apache Cloudberry 集群中。
export PGPASSWORD=gpadmin #源库中迁移用户的密码cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --full --truncate --compression
指定 database 迁移
将 Greenplum 6 集群中的 warehouse 数据库迁移到 Apache Cloudberry 集群中。
export PGPASSWORD=gpadmin #源库中迁移用户的密码cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --dbname="warehouse" --truncate --compression
指定模式(schema)迁移
将 Greenplum 6 集群中的 warehouse 数据库下的模式 sh1 迁移到 Apache Cloudberry 集群中。
export PGPASSWORD=gpadmin #源库中迁移用户的密码cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --truncate --compression --schema=warehouse.sh1
指定表迁移
将 Greenplum 6 集群中的 warehouse 数据库下的 public.cancel_accounts 迁移到 Apache Cloudberry 集群中。
export PGPASSWORD=gpadmin #源库中迁移用户的密码cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --truncate --compression --include-table="warehouse.public.cancel_accounts"
常用参数说明

迁移对象对比
数据迁移完成后,对源 Greenplum 6 集群和目标 Apache Cloudberry 集群中 warehouse 数据库中的 table、index、view、sequence、function 进行比对,确认 cbcopy 工具将 warehouse 数据库中的对象全部迁移到了 Apache Cloudberry 集群中。
对象检查(table、index、view、sequence)
源库 Greenplum 6
SELECT n.nspname as "Schema",c.relname as "Name",CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type",pg_catalog.pg_get_userbyid(c.relowner) as "Owner", CASE c.relstorage WHEN 'h' THEN 'heap' WHEN 'x' THEN 'external' WHEN 'a' THEN 'append only' WHEN 'v' THEN 'none' WHEN 'c' THEN 'append only columnar' WHEN 'p' THEN 'Apache Parquet' WHEN 'f' THEN 'foreign' END as "Storage"FROM pg_catalog.pg_class cLEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespaceWHERE c.relkind IN ('r','v','m','S','f','')AND c.relstorage IN ('h', 'a', 'c','x','f','v','')AND n.nspname <> 'pg_catalog'AND n.nspname <> 'information_schema'AND n.nspname !~ '^pg_toast'AND pg_catalog.pg_table_is_visible(c.oid)ORDER BY 1,2;
目标库 Apache Cloudberry
SELECT n.nspname as "Schema",c.relname as "Name",CASE c.relkind WHEN 'r' THEN 'table' WHEN 'd' THEN 'directory table' WHEN 'v' THEN 'view' WHEN 'm' THEN CASE c.relisdynamic WHEN true THEN 'dynamic table' ELSE 'materialized view' END WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type",pg_catalog.pg_get_userbyid(c.relowner) as "Owner",CASE a.amname WHEN 'ao_column' THEN 'append only columnar' WHEN 'ao_row' THEN 'append only' ELSE a.amname END as "Storage"FROM pg_catalog.pg_class cLEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespaceLEFT JOIN pg_catalog.pg_am am ON am.oid = c.relamLEFT JOIN pg_catalog.pg_am a ON a.oid = c.relamWHERE c.relkind IN ('r','p','v','m','S','f','')AND n.nspname <> 'pg_catalog'AND n.nspname !~ '^pg_toast'AND n.nspname <> 'information_schema'AND n.nspname !~ '^pg_toast'AND pg_catalog.pg_table_is_visible(c.oid)ORDER BY 1,2;
自定义函数检查
源库 Greenplum 6
SELECT n.nspname as "Schema",p.proname as "Name",pg_catalog.pg_get_function_result(p.oid) as "Result data type",pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",CASEWHEN p.proisagg THEN 'agg'WHEN p.proiswindow THEN 'window'WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'ELSE 'func'END as "Type"FROM pg_catalog.pg_proc pLEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespaceWHERE pg_catalog.pg_function_is_visible(p.oid)AND n.nspname <> 'pg_catalog'AND n.nspname <> 'information_schema'ORDER BY 1, 2, 4;3.4.2.2 目标库 Apache CloudberrySELECT n.nspname as "Schema",p.proname as "Name",pg_catalog.pg_get_function_result(p.oid) as "Result data type",pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",CASE p.prokindWHEN 'a' THEN 'agg'WHEN 'w' THEN 'window'WHEN 'p' THEN 'proc'ELSE 'func'END as "Type"FROM pg_catalog.pg_proc pLEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespaceWHERE pg_catalog.pg_function_is_visible(p.oid)AND n.nspname <> 'pg_catalog'AND n.nspname <> 'information_schema'ORDER BY 1, 2, 4;
cbcopy 参数

结语
通过本文对 cbcopy
工具的介绍与实战演示,我们可以看到 Cloudberry 在 兼容性、性能与易用性 方面对 Greenplum 的全面继承与优化。不论是完整集群迁移,还是数据库、模式乃至单表级别的迁移,cbcopy
都能以高效、可靠的方式实现从 Greenplum 向 Cloudberry 的无缝过渡。
对于希望延续 Greenplum 技术体系、又追求更开放生态和长期演进空间的用户而言,Apache Cloudberry 无疑是当前最具潜力的开源替代方案。未来,随着社区的不断发展与功能完善,Cloudberry 有望成为新一代数据仓库与大数据分析平台的核心力量。
👇🏻️扫码加入 Apache Cloudberry 交流群👇🏻️





