Greenplum支持行存和列存,支持堆表和AO表。
一、行存和列存的原理:
-
行存,以行为形式组织存储,一行是一个tuple,存在一起。当需要读取某列时,需要将这列前面的所有列都进行deform,所以访问第一列和访问最后一列的成本实际上是不一样的。
-
列存,以列为形式组织存储,每列对应一个或一批文件。读取任一列的成本是一样的,但是如果要读取多列,需要访问多个文件,访问的列越多,开销越大。
二、堆表和AO表的原理
1、堆表,实际上就是PG的堆存储,堆表的所有变更都会产生REDO,可以实现时间点恢复。但是堆表不能实现逻辑增量备份(因为表的任意一个数据块都有可能变更,不方便通过堆存储来记录位点。)。
一个事务结束时,通过clog以及REDO来实现它的可靠性。同时支持通过REDO来构建MIRROR节点实现数据冗余。
2、AO(append only)表,看名字就知道,只追加的存储,删除更新数据时,通过另一个BITMAP文件来标记被删除的行,通过bit以及偏移对齐来判定AO表上的某一行是否被删除。
事务结束时,需要调用FSYNC,记录最后一次写入对应的数据块的偏移。(并且这个数据块即使只有一条记录,下次再发起事务又会重新追加一个数据块)同时发送对应的数据块给MIRROR实现数据冗余。
因此AO表不适合小事务,因为每次事务结束都会FSYNC,同时事务结束后这个数据块即使有空余也不会被复用。(你可以测试一下,AO表单条提交的IO放大很严重)。
虽然如此,AO表非常适合OLAP场景,批量的数据写入,高压缩比,逻辑备份支持增量备份,因此每次记录备份到的偏移量即可。加上每次备份全量的BITMAP删除标记(很小)。
三、数据库提供的备份和恢复工具
1、三种工具
主要分为以下3种,具体试用方法请参考官方文档:
- gpbackup/gprestore
应用场景:用于并行备份或恢复
文档:http://docs.greenplum.org/6-10/admin_guide/managing/backup-gpbackup.html
- pg_dump/pg_restore
应用场景:用于非并行备份或恢复,少量数据备份
说明:pg_dumpall在内部调用pg_dump
文档:
(1) http://www.postgres.cn/docs/9.4/app-pgdump.html
(2) http://www.postgres.cn/docs/9.4/app-pg-dumpall.html
- copy…to…/copy…from…
应用场景:用于非并行备份或恢复,多用于导出/导入数据文件,例如csv格式等
文档:http://www.postgres.cn/docs/9.4/sql-copy.html
2、备份一个表的DDL语句与恢复
- (1) 备份
可以使用pg_dump导出,例如:
pg_dump -t public.t_test -s -c -f ddl_test.sql
其中:
-f 把输出发往指定的文件。这里的ddl_test.sql即为输出的文件名;
-t 只转储出匹配table的表(或视图、序列、外表)。 可以使用多个-t选项匹配多个表,public.t_test即为带模式名的表名;
-s 只输出对象定义(模式),不输出数据;
-c 输出命令在输出创建数据库命令之前先清理(drop)该数据库对象。
- (2)恢复
psql -d newdb -f ddl_test.sql
3、gpbackup与gprestore使用
- (1)全量备份
gpbackup --dbname studydb --backup-dir /data/gpdb/backup --debug
- (2)恢复
gprestore --timestamp 20201210145024 --backup-dir /data/gpdb/backup --debug
三、AO表的增量备份原理
1、AO表的增量备份与恢复
gpbackup与gprestore可以实现对AO表的增量备份功能。在使用时要实现增量恢复,必须包含与增量备份相同的–backup-dir选项以及–leaf-partition-data和–incremental选项。即:
gpbackup --dbname studydb --backup-dir /data/gpdb/backup --leaf-partition-data --incremental --debug
gprestore --create-db --timestamp 20201210145024 --backup-dir /data/gpdb/backup --leaf-partition-data --debug
以上命令的–backup-dir与–leaf-partition-data必须都相同。
2、AO表的增量备份分析
按照如下SQL语句顺执行,注意观测SELECT modcount FROM gp_toolkit.__gp_aoseg(‘test_ao’)语句的值变化:
create table "test_ao"(
"id" int,
"name" text
) with (appendonly=true)
distributed by ("id");
SELECT modcount FROM gp_toolkit.__gp_aoseg('test_ao') -- 查询为空
INSERT INTO "test_ao" ("id","name") values (1,'hello'); -- 插入第1条数据
SELECT modcount FROM gp_toolkit.__gp_aoseg('test_ao'); -- 为 1
INSERT INTO "test_ao" ("id","name") values (2,'test'); -- 插入第2条数据
SELECT modcount FROM gp_toolkit.__gp_aoseg('test_ao'); -- 为 2
UPDATE "test_ao" SET "name"='xxxx' where "id"='2'; -- 更新1条记录
SELECT modcount FROM gp_toolkit.__gp_aoseg('test_ao'); -- 为 3
INSERT INTO "test_ao" ("id","name") values (3,'yyyyyy'); -- 插入第3条数据
SELECT modcount FROM gp_toolkit.__gp_aoseg('test_ao'); -- 为 4
DELETE FROM "test_ao" WHERE "id"='3'; -- 删除1条记录
SELECT modcount FROM gp_toolkit.__gp_aoseg('test_ao'); -- 为 5
分析可知:
(1) 当插入或修改数据时,通过gp_toolkit.__gp_aoseg查询可发现查询的数字随操作的记录数而增加。
(2) 更新数据并非真正更改记录值,而是通过将旧数据标记为删除,再插入新的数据来实现。
(3) 删除数据也会有数据记录
四、Greenplum的垃圾空间回收
Greenplum支持行储存(HEAP储存)与列(append-only)储存,对于AO存储,虽然是appendonly,但实际上GP是支持DELETE和UPDATE的,被删除或更新的行,通过BITMAP来标记删除与修改。AO存储是块级组织,当一个块内的数据大部分都被删除或更新掉时,扫描它浪费的成本实际上是很高的。而PostgreSQL是通过HOT技术以及autovacuum来避免或减少垃圾的。但是Greenplum没有自动回收的worker进程,所以需要人为的触发。接下来就分析AO表与HEAP表的问题以及如何解答,执行空间的释放有3中方法分别是:
-
1、执行VACUUM。(当膨胀率大于gp_appendonly_compaction_threshold参数时),为共享锁。
-
2、执行VACUUM FULL。(不管gp_appendonly_compaction_threshold参数的设置,都会回收垃圾空间。),为DDL锁,慎用这个命令,会把CPU与IO沾满。
-
3、执行重分布。(不管gp_appendonly_compaction_threshold参数,都会回收垃圾空间。),为DDL锁。
本文地址:https://blog.csdn.net/inrgihc/article/details/110953633