greenplum属于分布式的数据库,MPP+Share nothing的体系,查询的效率很快.不过,这是建立在数据分散均匀的基础上的.如果DK值设置不合理的话,完全有可能出现所有数据落在单个节点上的情况,这就体现不出优势来.因此,DK值的设置是否合适是建表的时候,需要考虑的重要因素之一.
查看表(table_name)的数据在节点的分布情况:
select
gp_segment_id,
count
(
*
)
from
table_name
group
by
gp_segment_id;
如果数据有严重倾斜的话,即某些节点的数据量过大,表示DK值需要重新调整.调整语句为alter table table_name set distirbuted by(col1,col2,...);
现在有个问题是:如何发现哪些DK值设置不合理的表呢?可以参照之前写的文章: 数据分布查看 , 执果索因调整
这里介绍的是如何把DK值展现出现,一般设置单列(该列为日期类型,每天一份的话)的表,就很有可能出现DK值不合理的情况。我们需要利用到三张表:
pg_class --object属性表,relkind表示object属性,'r'代表table
pg_attribute --展现详细的列
gp_distribution_policy --存储DK值
首先,创建一个类型,用来显示function的结果集.
create
type dk_table_type as
(
table_name
varchar
,
dk_cols
varchar
);
然后,用上面三张表组合起来,得到相应的所需要的结果信息.
CREATE
OR
REPLACE
FUNCTION
get_table_dk()
RETURNS
SETOF dk_table_type
AS
$BODY$
DECLARE
v_cur_tb
cursor
for
select
d.nspname
||
'
.
'
||
a.relname,b.attname
from
pg_class a
inner
join
pg_attribute b
on
a.oid
=
b.attrelid
inner
join
gp_distribution_policy c
on
a.oid
=
c.localoid
inner
join
pg_namespace d
on
a.relnamespace
=
d.oid
where
a.relkind
=
'
r
'
and
b.attnum
=any
(c.attrnums)
order
by
d.nspname
||
'
.
'
||
a.relname,b.attname,b.attnum;
v_tb
varchar
(
500
):
=
''
;
v_tb_new
varchar
(
500
):
=
''
;
v_dk_col
varchar
(
100
):
=
''
;
v_dk_cols
varchar
(
1000
):
=
''
;
v_record
dk_table_type;
BEGIN
open
v_cur_tb;
loop
fetch
v_cur_tb
into
v_tb_new,v_dk_col;
if
not
found
THEN
exit
;
end
if
;
if
v_tb
=
''
and
v_dk_cols
=
''
then
v_tb :
=
v_tb_new;
v_dk_cols:
=
v_dk_col;
ELSEIF v_tb
<>
v_tb_new
THEN
select
v_tb,v_dk_cols
into
v_record;
return
next
v_record;
v_tb :
=
v_tb_new;
v_dk_cols:
=
v_dk_col;
ELSE
v_dk_cols:
=
v_dk_cols
||
'
,
'
||
v_dk_col;
end
if
;
end
loop;
select
v_tb,v_dk_cols
into
v_record;
return
next
v_record;
close
v_cur_tb;
end
;
$BODY$
LANGUAGE plpgsql VOLATILE;
然后,执行select * from get_table_dk() 就可以获得表以及其对应的DK值(列),从而可以直观的发现是否有些表需要调整,此时就用上面的gp_segment_id来验证.如果是的话,就进行相应的调整.

