本节书摘来自华章出版社《Greenplum企业应用实战》一书中的第3章,第3.3节,作者 何勇 陈晓峰,更多章节内容可以访问云栖社区“华章计算机”公众号查看
3.3 数据分布
由于Greenplum是分布式的架构,为了充分体现分布式架构的优势,我们有必要了解数据是如何分散在各个数据节点上的,有必要了解数据倾斜对数据加载、数据分析、数据导出的影响。
3.3.1 数据分散情况查看
我们来简单做个测试,首先,利用generate_series和repeat函数生成一些测试数据,代码如下:
create table test_distribute_1
as
select a as id
,round(random()) as flag
, repeat('a',1024) as value
from generate_series(1,5000000)a;
500万数据分散在6个数据节点,利用下面这个SQL可以查询数据的分布情况(SQL在后面5.8.4中将会介绍):
testDB=# select gp_segment_id,count(*)
testDB-# from test_distribute_1
testDB-# group by 1;
gp_segment_id | count
---------------+--------
1 | 833396
4 | 833297
5 | 833294
3 | 833309
2 | 833359
0 | 833345
(6 rows)
上述SQL中的group by 1,其中1代表select后面的第一个字段,即gp_segment_id。
3.3.2 数据加载速度影响
接下来将通过实验来测试在分布键不同的情况下数据加载的速度。
(1)数据倾斜状态下的数据加载
1)测试数据准备,将测试数据导出:
testDB=# copy test_distribute_1 to '/home/gpadmin/data/test_distribute.dat' with delimiter '|';
COPY 5000000
2)建立测试表,以flag字段为分布键:
testDB=# create table test_distribute_2 as select * from test_distribute_1 limit 0 distributed by(flag);
SELECT 0
3)执行数据导入:
$ time psql -h localhost -d testDB -c "copy test_distribute_2 from stdin with delimiter '|'" < /home/gpadmin/data/test_distribute.dat
real 14m1.381s
user 0m24.080s
sys 0m26.387s
4)由于分布键flag取值只有0和1,因此数据只能分散到两个数据节点,如下:
testDB=# select gp_segment_id,count(*) from table_distribute_4 group by 1;
gp_segment_id | count
---------------+---------
3 | 2498434
2 | 2501566
(2 rows)
Time: 50751.740 ms
5)由于数据分布在2和3节点,对应Primary Segment在dell3、Mirror节点dell4上,可通过以下SQL查询gp_segment_configuration获得:
testDB=# select dbid,content,role,port,hostname from gp_segment_configuration
testDB-# where content in(2,3) order by role;
dbid | content | role | port | hostname
------+---------+------+-------+----------
11 | 3 | m | 60001 | dell4
10 | 2 | m | 60000 | dell4
5 | 3 | p | 50001 | dell3
4 | 2 | p | 50000 | dell3
(4 rows)
在执行数据导入期间,Greenplum Performance Monitor页面可监控到:仅有dell3和dell4两台服务器有磁盘和CPU消耗,如图3-7所示。
Greenplum Performance Monitor的安装部署,将在10.2.1—GPmonitor介绍中介绍。
(2)数据分布均匀状态下的数据加载
1)建立测试表,以id字段为分布键:
testDB=# create table test_distribute_3 as select * from test_distribute_1 limit 0 distributed by(id);
SELECT 0
2)执行数据导入:
$ time psql -h localhost -d testDB -c "copy test_distribute_3 from stdin with delimiter '|'" < /home/gpadmin/data/test_distribute.dat
real 9m40.607s
user 0m24.364s
sys 0m24.491s
3)由于分布键id取值顺序分布,因此数据可均匀分散至所有数据节点,如下:
testDB=# select gp_segment_id,count(*) from test_distribute_3 group by 1;
gp_segment_id | count
---------------+--------
1 | 833396
4 | 833297
5 | 833294
3 | 833309
2 | 833359
0 | 833345
(6 rows)
Time: 17999.875 ms
在执行数据导入期间,Greenplum Performance Monitor页面可监控到:3台服务器的所有节点都有磁盘和CPU消耗,可见,在数据均匀的情况下,可以利用更多的机器进行工作,性能也比较高,如图3-8所示。
3.3.3 数据查询速度影响
(1)数据倾斜状态下的数据查询
testDB=# select gp_segment_id,count(*),max(length(value)) from test_distribute_2 group by 1;
gp_segment_id | count | max
---------------+---------+------
3 | 2498434 | 1024
2 | 2501566 | 1024
(2 rows)
Time: 79840.885 ms
由于数据分布在2和3节点上,即对应dell3和相应的Mirror节点dell4上,但是数据查询只需要Primary节点,故只有dell3节点有磁盘消耗,如图3-9所示。
(2)数据分布均匀状态下的数据查询
testDB=# select gp_segment_id,count(*),max(length(value)) from test_distribute_3 group by 1;
gp_segment_id | count | max
---------------+--------+------
1 | 833396 | 1024
3 | 833309 | 1024
5 | 833294 | 1024
4 | 833297 | 1024
2 | 833359 | 1024
0 | 833345 | 1024
(6 rows)
Time: 6976.840 ms
由于数据分布在所有节点上,故所有服务器都有磁盘消耗,从而大大提升了数据查询的性能。