问题描述
在生产环境中,遇到这样的一个问题,用函数pg_relation_size统计分区表的各个子分区表时,直接统计出来的数据是正确的,但关联自己定义的配置表后,统计出来的结果就有问题,GP4和GP6版本都有这情况出现
场景复现
建分区表并插入数据
drop table tmp;
create table public.tmp(
id int
,par text
,info text
) distributed by (id)
PARTITION BY LIST(par)
(
PARTITION p00 VALUES('00'),
PARTITION p01 VALUES('01'),
PARTITION p02 VALUES('02'),
PARTITION p03 VALUES('03'),
PARTITION p04 VALUES('04'),
PARTITION p05 VALUES('05'),
PARTITION p06 VALUES('06'),
PARTITION p07 VALUES('07'),
PARTITION p08 VALUES('08'),
PARTITION p09 VALUES('09')
);
insert into public.tmp
select generate_series(1,10000),'00','yejf';
建配置表并插入数据
drop table public.cfg;
create table public.cfg(schemaname text,tablename text);
insert into public.cfg values('public','tmp');
不关联配置表时统计结果正常
select pg_relation_size(p.partitionschemaname||'.'||p.partitiontablename) data_size
,p.partitionschemaname||'.'||p.partitiontablename tablename
from pg_partitions p
--join public.cfg tb on p.schemaname=tb.schemaname and p.tablename=tb.tablename
where p.schemaname||'.'||p.tablename='public.tmp';
结果数据
2097152;"public.tmp_1_prt_p00"
关联配置表时统计结果异常
select pg_relation_size(p.partitionschemaname||'.'||p.partitiontablename) data_size
,p.partitionschemaname||'.'||p.partitiontablename tablename
from pg_partitions p
join public.cfg tb on p.schemaname=tb.schemaname and p.tablename=tb.tablename
where p.schemaname||'.'||p.tablename='public.tmp';
结果数据
32768;"public.tmp_1_prt_p00"
原因是pg_relation_size跑到计算节点上执行了,这样的话,只取到了一个计算节点实例的表尺寸数据,这问题在GP6之前的版本都没有好的办法解决,只能改写sql,确保函数在master上执行,而不是下发执行。
在GP6版本中,可以对表public.cfg建replicated表,结合gp_dist_random函数,就可以确保函数在所有实例上被执行,数据再进行分组汇总统计即可得到正确的结果。代码如下
drop table public.cfg;
create table public.cfg(schemaname text,tablename text)
DISTRIBUTED REPLICATED;
insert into public.cfg values('public','tmp');
统计结果
select tablename,sum(data_size)
from(
select pg_relation_size(p.partitionschemaname||'.'||p.partitiontablename) data_size
,p.partitionschemaname||'.'||p.partitiontablename tablename
from pg_partitions p
join gp_dist_random('public.cfg') tb on p.schemaname=tb.schemaname and p.tablename=tb.tablename
where p.schemaname||'.'||p.tablename='public.tmp'
)t
group by tablename;
--
2097152;"public.tmp_1_prt_p00"
文章转载自叶同学专栏,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




