Greenplum 列存表(AO表)的膨胀和垃圾检查与空间收缩
1.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锁
。
3、执行重分布。(不管gp_appendonly_compaction_threshold
参数,都会回收垃圾空间。),为DDL锁
。
2.查看表的储存类型
名字 | 引用 | 描述 |
---|---|---|
regproc | pg_proc | 函数名字 |
reprocedure | pg_proc | 带参数类型的函数 |
regoper | pg_operator | 操作符名 |
regoperator | pg_operator | 带参数类型的操作符名 |
regclass | pg_class | 关系名 |
2.1 执行查看命令
analticdb=# \timing
Timing is on.
analticdb=# select distinct relstorage from pg_class ;
relstorage
------------
x
v
h
c
(4 rows)
Time: 6.256 ms
analticdb=#
2.2 名词解释
timing
打开SQL的执行时间
h
= 堆表(heap)、索引
a
= append only row存储表
c
= append only column存储表
x
= 外部表(external table)
v
= 视图
3.AO表分析
3.1 查看当前数据库中有哪些AO表
analticdb=# select t2.nspname, t1.relname from pg_class t1, pg_namespace t2 where t1.relnamespace=t2.oid and relstorage in ('c', 'a');
nspname | relname
---------+-------------------------
public | dwm_order_goods_sales_c
public | dwm_order_c
(2 rows)
Time: 7.748 ms
可以看出来 dwm_order_goods_sales_c
、dwm_order_c
为AO表
3.2 查看AO表的膨胀率
表的膨胀率也就是表中执行DELETE
和UPDATE
产生的垃圾
3.2.1 执行查看命令
analticdb=# select * from gp_toolkit.__gp_aovisimap_compaction_info('public.dwm_order_c2'::regclass);
NOTICE: gp_appendonly_compaction_threshold = 10
content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+----------+---------------------+-----------------+----------------+----------------
2 | 2 | f | 0 | 0 | 0.00
3 | 1 | t | 3 | 8 | 37.50
3 | 2 | t | 5 | 7 | 71.43
0 | 2 | f | 0 | 0 | 0.00
1 | 2 | f | 0 | 0 | 0.00
(5 rows)
3.2.2 名词解释
public
: schema的名字
dwm_order_c2
:当前schema下的表
gp_appendonly_compaction_threshold
: AO的压缩进程,目前设置的是10
content
:对应gp_configuration.content表示greenplum每个节点的唯一编号。
datafile
:这条记录对应的这个表的其中一个数据文件的编号,每个数据文件假设1GB。
hidden_tupcount
:有多少条记录已更新或删除(不可见)。
total_tupcount
:总共有多少条记录(包括已更新或删除的记录)。
percent_hidden
:不可见记录的占比。如果这个占比大于gp_appendonly_compaction_threshold参数,那么执行vacuum时,会收缩这个数据文件。
compaction_possible
:这个数据文件是否可以被收缩。(通过gp_appendonly_compaction_threshold参数和percent_hidden值判断)。
在以上中可以看出在3节点上的第1号文件有8记录其中有3条记录被更新或删除,其中不可见的比例为37.50%
3.3 检查系统中膨胀率超过N的AO表
3.3.1 执行命令
analticdb=# select * from (select t2.nspname, t1.relname, (gp_toolkit.__gp_aovisimap_compaction_info(t1.oid)).* from pg_class t1, pg_namespace t2 where t1.relnamespace=t2.oid and relstorage in ('c', 'a')) t where t.percent_hidden > 0.2;
NOTICE: gp_appendonly_compaction_threshold = 10
nspname | relname | content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+--------------+---------+----------+---------------------+-----------------+----------------+----------------
public | dwm_order_c2 | 0 | 2 | t | 3 | 8 | 37.50
public | dwm_order_c2 | 1 | 2 | t | 5 | 7 | 71.43
(2 rows)
Time: 24.654 ms
以上命令是查询膨胀率超过千分之2的AO表
3.3.2 名词解释
nspname
: 表示查询的schema的名字
relname
: 是当前schema的表的名字
在以上数据中可以看出在每个节点上的膨胀率也不同
3.4 查看膨胀数据的占用大小
analticdb=# select pg_size_pretty(pg_relation_size('public.dwm_order_c2'));
pg_size_pretty
----------------
31 kB
(1 row)
Time: 1.923 ms
在以上可以看出膨胀率占用了31KB的空间
3.5 查看表的行数
analticdb=# select count(*) from public.dwm_order_c2;
count
-------
7
(1 row)
Time: 9.726 ms
3.6 释放膨胀的空间
在以上的数据中可以看出膨胀率大于了gp_appendonly_compaction_threshold
的值可以直接使用vacuum
命令进行收缩
analticdb=# vacuum public.dwm_order_c2;
VACUUM
Time: 127.505 ms
3.7 查看释放后的占用空间
3.7.1 释放膨胀空间
analticdb=# select pg_size_pretty(pg_relation_size('public.dwm_order_c2'));
pg_size_pretty
----------------
7984 bytes
(1 row)
Time: 1.434 ms
以上可以看出已经释放了大部分的空间
3.7.2 再次查看AO的膨胀率
analticdb=# select * from (select t2.nspname, t1.relname, (gp_toolkit.__gp_aovisimap_compaction_info(t1.oid)).* from pg_class t1, pg_namespace t2 where t1.relnamespace=t2.oid and relstorage in ('c', 'a')) t where t.percent_hidden > 0.01;
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
NOTICE: gp_appendonly_compaction_threshold = 10
nspname | relname | content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+---------+---------+----------+---------------------+-----------------+----------------+----------------
(0 rows)
Time: 22.552 ms
以上命令是查询膨胀率超过万分之1的AO表
3.8 再次查看表的行数
analticdb=# select count(*) from public.dwm_order_c2;
count
-------
7
(1 row)
Time: 8.169 ms
从以上可以看出与第一次查询出来的行数一致。
3.9 使用更改随机的方式释放空间
3.9.1 查看膨胀占用空间
analticdb=# select * from (select t2.nspname, t1.relname, (gp_toolkit.__gp_aovisimap_compaction_info(t1.oid)).* from pg_class t1, pg_namespace t2 where t1.relnamespace=t2.oid and relstorage in ('c', 'a')) t where t.percent_hidden > 0.01;
NOTICE: gp_appendonly_compaction_threshold = 10
nspname | relname | content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+--------------+---------+----------+---------------------+-----------------+----------------+----------------
public | dwm_order_c2 | 2 | 4 | f | 5 | 0 | 100.00
public | dwm_order_c2 | 3 | 2 | f | 2 | 7 | 100.00
(2 rows)
Time: 22.410 ms
3.9.2 随机改变表的分布键
analticdb=# alter table public.dwm_order_c2 set with (reorganize=true) distributed randomly;
ALTER TABLE
Time: 85.755 ms
3.9.3 查看释放后的空间
analticdb=# select * from (select t2.nspname, t1.relname, (gp_toolkit.__gp_aovisimap_compaction_info(t1.oid)).* from pg_class t1, pg_namespace t2 where t1.relnamespace=t2.oid and relstorage in ('c', 'a')) t where t.percent_hidden > 0.01;
NOTICE: gp_appendonly_compaction_threshold = 10
nspname | relname | content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+---------+---------+----------+---------------------+-----------------+----------------+----------------
(0 rows)
Time: 28.697 ms
注意在执行随机分布键是在非业务的时候执行,执行distribute会执行排它锁不,要堵塞业务。
3.10 使用多分布键的形式释放空间
3.10.1 执行重新分布命令
analticdb=# alter table public.dwm_order_c2 set with (reorganize=true) distributed by (id_d_w_d);
ALTER TABLE
Time: 69.174 ms
3.10.2 查看数据的膨胀率
analticdb=# select * from (select t2.nspname, t1.relname, (gp_toolkit.__gp_aovisimap_compaction_info(t1.oid)).* from pg_class t1, pg_namespace t2 where t1.relnamespace=t2.oid and relstorage in ('c', 'a')) t where t.percent_hidden > 0.01;
NOTICE: gp_appendonly_compaction_threshold = 10
nspname | relname | content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+---------+---------+----------+---------------------+-----------------+----------------+----------------
(0 rows)
Time: 18.763 ms
注意在执行随机分布键是在非业务的时候执行,执行distribute会执行排它锁不,要堵塞业务。
4. AO表总结
4.1 查看表的行的个数
select count(*) from public.dwm_order_c2;
4.2 更新数据的行数与占用大小
4.2.1 更新数据
analticdb=# update public.dwm_order_c2 set order_type='2' where order_type='1';
UPDATE 7
Time: 41.978 ms