前言:
与其它数据库相比,GP的表最大的不同是它一定是分区的,也就是表中的所有记录都会依据相关算法打散,分布到所有的segment当中,从而在充分利用硬件资源的同时,最大化访问数据的IO,这种特性对于数据仓库应用是非常有帮助的。GP提供两种打散数据的算法,一种是HASH算法,参见例子一,在定义表的时候,通过distributed by指定表中的某个列或者某个列的组合作为HASH键,相同HASH键的记录会放在同一个SEGM中。
所以,GP建议一般选择记录分布均匀的键作为HASH键使用,从而保证表中的记录可以均匀分布到所有SEGMENT上。如果表上定义了主键或者唯一键,则这些键值列必须作前导列出现在分布键当中。假如例子一的PROD_ID是主键或者唯一键,那么它必须出现在HASH键中,并且放在第一位。 如果定义表的时候,没有指定distributed子句,系统使用第一个列作为HASH键使用。另一种数据打散的算法是平均分配法(ROUND-ROBIN),参见例子二, 假设有三个段,那么这种算法会把第一条记录放在段1, 第二条记录放在段2,第三条记录放在段3,第四条记录放在段四,以此类推,直到所有记录发放完为止。这种算法比较适合表中的字段存在严重数据倾斜的情况。
测试的表:下面两张表的记录条数及字段内容都是一致的。
1、c_stat_serv_arrear_m_h ,分布键是serv_h和cell_id,如下图,数据分布比较均匀。
2、c_stat_serv_arrear_m,,分布键是serv_h,如下图,数据分布比较均匀。
测试1(每个SQL执行3次): 1、select gp_segment_id,* from c_stat_serv_arrear_m t where serv_id = 11566944 and gp_segment_id =10; 查询总耗时: 844 ms. 检索到 1 行。 查询总耗时: 750 ms. 检索到 1 行。 查询总耗时: 922 ms. 检索到 1 行。 AVG:839 ms 2、select gp_segment_id,* from c_stat_serv_arrear_m t where serv_id in( 11566944,8460939) --11566944,8460939是在同一个实例下面,实例10 AVG:880 ms 3、select gp_segment_id,* from c_stat_serv_arrear_m t where serv_id in( 11566944,13363817) --11566944,13363817在不同实例,实例10,实例1 查询总耗时: 875 ms. 检索到 2 行。 4、select gp_segment_id,* from c_stat_serv_arrear_m t where serv_id in( 8460939,11566944,13363817,16391864) --4个serv_id在两个不同的实例 查询总耗时: 891 ms. 检索到 4 行。 小总结:根据分布键(一个字段)查询,同一个实例查询和不同实例查询,返回同样的数据量的时间是差不多的。 ---------------------------------------------------------------------------------------------- 测试2(每个SQL执行3次): 1、select gp_segment_id,* from c_stat_serv_arrear_m_h t where serv_id =11566944 查询总耗时: 110 ms. 检索到 1 行。 查询总耗时: 94 ms. 检索到 1 行。 查询总耗时: 78 ms 检索到 1 行。 AVG:94 ms 2、select gp_segment_id,* from c_stat_serv_arrear_m_h t where serv_id in( 11566944,3602836783) --11566944,3602836783是在同一个实例 查询总耗时: 180 ms. 检索到 2 行。 3、select gp_segment_id,* from c_stat_serv_arrear_m t where serv_id in( 11566944,13363817) --11566944,13363817是在不同实例 查询总耗时: 190 ms. 检索到 2 行。 4、select gp_segment_id,* from c_stat_serv_arrear_m_h t where serv_id in( 11566944,13363817,3602836783) 查询总耗时: 265 ms. 检索到 3 行。 5、select gp_segment_id,* from c_stat_serv_arrear_m_h t where serv_id = 11566944 and cell_id=8004 查询总耗时: 78 ms. 检索到 1 行。 小总结:混合分布键(两个字段)查询,用其中一个分布键查询和混合分布键一起查询,效率差不多 ---------------------------------------------------------------------------------------------- 测试3:c_stat_serv_arrear_m_cell 分布键是cell_id 1、select gp_segment_id,* from c_stat_serv_arrear_m_cell t where serv_id = 17022892 查询总耗时: 469 ms. 检索到 1 行。 2、select gp_segment_id,* from c_stat_serv_arrear_m_cell t where serv_id = 17022892 and cell_id =368192 查询总耗时: 63 ms. 检索到 1 行。 3、select gp_segment_id,* from c_stat_serv_arrear_m_cell t where serv_id in ( 17022892,11566944) 查询总耗时: 844 ms. 检索到 2 行。 4、select gp_segment_id,* from c_stat_serv_arrear_m_cell t where cell_id in(368192 ,8004) and serv_id in ( 17022892,11566944) 查询总耗时: 640 ms. 检索到 2 行。 小总结:混合分布键(两个字段)查询,分布键查询与不用分布键查询,速度差别很大 ----------------------------------------------------------------------------------------------