Skip to content

Commit 9980d23

Browse files
committed
new doc
1 parent 47ff0e6 commit 9980d23

File tree

6 files changed

+166
-7
lines changed

6 files changed

+166
-7
lines changed

201708/20170818_02.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,15 +392,15 @@ postgres=# explain analyze select c398,count(*),sum(c399),avg(c399),min(c399),ma
392392
(22 rows)
393393
```
394394

395-
小结,对于非分布键的分组聚合请求,Greenplum采用了3阶段聚合
395+
对于非分布键的分组聚合请求,Greenplum采用了多阶段聚合如下
396396

397397
第一阶段,在SEGMENT本地聚合。(需要扫描所有数据,这里不同存储,前面的列和后面的列的差别就体现出来了,行存储的deform开销,在对后面的列进行统计时性能影响很明显。)
398398

399-
第二阶段,根据分组字段,重分布数据。(需要重分布需要用到的字段。)
399+
第二阶段,根据分组字段,将结果数据重分布。(重分布需要用到的字段,此时结果很小。)
400400

401-
第三阶段,在SEGMENT本地聚合。(需要对重分布后的数据进行聚合。)
401+
第三阶段,再次在SEGMENT本地聚合。(需要对重分布后的数据进行聚合。)
402402

403-
第四阶段,返回结果
403+
第四阶段,返回结果给master,有必要的话master节点调用聚合函数的final func(已经是很少的记录数和运算量)
404404

405405
## 参考
406406
[《PostgreSQL 向量化执行插件(瓦片式实现) 10x提速OLAP》](../201702/20170225_01.md)

201708/20170821_01.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Greenplum 内存与负载管理最佳实践
1+
## Greenplum 内存与负载管理(resource queue)最佳实践
22
33
### 作者
44
digoal

201708/20170821_02.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
## 分布式DB中数据倾斜的原因和解法 - 阿里云HybridDB for PostgreSQL最佳实践
2+
3+
### 作者
4+
digoal
5+
6+
### 日期
7+
2017-08-21
8+
9+
### 标签
10+
PostgreSQL , Greenplum , query倾斜 , 存储倾斜 , OOM , disk full , 短板 , 数据分布
11+
12+
----
13+
14+
## 背景
15+
对于分布式数据库来说,QUERY的运行效率取决于最慢的那个节点。
16+
17+
![pic](20170821_02_pic_001.jpg)
18+
19+
当数据出现倾斜时,某些节点的运算量可能比其他节点大。除了带来运行慢的问题,还有其他的问题,例如导致OOM,或者DISK FULL等问题。
20+
21+
## 出现数据倾斜的原因和解决办法
22+
1、分布键选择不正确,导致数据存储分布不均。
23+
24+
例如选择的字段某些值特别多,由于数据是按分布键VALUE的HASH进行分布的,导致这些值所在的SEGMENT的数据可能比而其他SEGMENT多很多。
25+
26+
分布键的选择详见:
27+
28+
[《Greenplum 最佳实践 - 数据分布黄金法则 - 分布列与分区的选择》](../201607/20160719_02.md)
29+
30+
2、查询导致的数据重分布,数据重分布后,数据不均。
31+
32+
例如group by的字段不是分布键,那么运算时就需要重分布数据。
33+
34+
解决办法1:
35+
36+
由于查询带来的数据倾斜的可能性非常大,所以Greenplum在内核层面做了优化,做法是:
37+
38+
先在segment本地聚合产生少量记录,将聚合结果再次重分布,重分布后再次在segment聚合,最后将结果发到master节点,有必要的话在master节点调用聚合函数的final func(已经是很少的记录数和运算量)。
39+
40+
例子:
41+
42+
tbl_ao_col表是c1的分布键,但是我们group by使用了c398字段,因此看看它是怎么做的呢?请看执行计划的解释。
43+
44+
```
45+
postgres=# explain analyze select c398,count(*),sum(c399),avg(c399),min(c399),max(c399) from tbl_ao_col group by c398;
46+
QUERY PLAN
47+
--------------------------------------------------------------------------------------------------------------------------------------------------------
48+
Gather Motion 48:1 (slice2; segments: 48) (cost=123364.18..123582.28 rows=9693 width=96)
49+
// 返回结果
50+
Rows out: 10001 rows at destination with 120 ms to end, start offset by 1.921 ms.
51+
-> HashAggregate (cost=123364.18..123582.28 rows=202 width=96)
52+
// 重分布后再次聚合。
53+
Group By: tbl_ao_col.c398
54+
Rows out: Avg 208.4 rows x 48 workers. Max 223 rows (seg17) with 0.001 ms to first row, 54 ms to end, start offset by 35 ms.
55+
-> Redistribute Motion 48:48 (slice1; segments: 48) (cost=122928.00..123121.86 rows=202 width=96)
56+
// 第一次聚合后,记录数以及降低到了几千行,因此重分布后即使出现倾斜,关系也不大。
57+
Hash Key: tbl_ao_col.c398
58+
Rows out: Avg 8762.2 rows x 48 workers at destination. Max 9422 rows (seg46) with 31 ms to end, start offset by 63 ms.
59+
-> HashAggregate (cost=122928.00..122928.00 rows=202 width=96)
60+
// 这一步是在segment节点聚合
61+
Group By: tbl_ao_col.c398
62+
Rows out: Avg 8762.2 rows x 48 workers. Max 8835 rows (seg2) with 0.004 ms to first row, 8.004 ms to end, start offset by 82 ms.
63+
-> Append-only Columnar Scan on tbl_ao_col (cost=0.00..107928.00 rows=20834 width=16)
64+
Rows out: 0 rows (seg0) with 28 ms to end, start offset by 64 ms.
65+
Slice statistics:
66+
(slice0) Executor memory: 377K bytes.
67+
(slice1) Executor memory: 1272K bytes avg x 48 workers, 1272K bytes max (seg0).
68+
(slice2) Executor memory: 414K bytes avg x 48 workers, 414K bytes max (seg0).
69+
Statement statistics:
70+
Memory used: 128000K bytes
71+
Settings: optimizer=off
72+
Optimizer status: legacy query optimizer
73+
Total runtime: 122.173 ms
74+
(22 rows)
75+
```
76+
77+
对于非分布键的分组聚合请求,Greenplum采用了多阶段聚合如下:
78+
79+
第一阶段,在SEGMENT本地聚合。(需要扫描所有数据,这里不同存储,前面的列和后面的列的差别就体现出来了,行存储的deform开销,在对后面的列进行统计时性能影响很明显。)
80+
81+
第二阶段,根据分组字段,将结果数据重分布。(重分布需要用到的字段,此时结果很小。)
82+
83+
第三阶段,再次在SEGMENT本地聚合。(需要对重分布后的数据进行聚合。)
84+
85+
第四阶段,返回结果给master,有必要的话master节点调用聚合函数的final func(已经是很少的记录数和运算量)。
86+
87+
3、内核只能解决一部分查询引入的数据重分布倾斜问题,还有一部分问题内核没法解决。例如窗口查询。
88+
89+
```
90+
postgres=# explain select * from (select row_number() over (partition by c2 order by c3) as rn , * from tbl_ao_col) t where rn=1;
91+
QUERY PLAN
92+
-------------------------------------------------------------------------------------------------------------------------
93+
Gather Motion 48:1 (slice2; segments: 48) (cost=5294619.34..5314619.34 rows=1000 width=3208)
94+
-> Subquery Scan t (cost=5294619.34..5314619.34 rows=21 width=3208)
95+
Filter: rn = 1
96+
-> Window (cost=5294619.34..5302119.34 rows=20834 width=3200)
97+
Partition By: tbl_ao_col.c2
98+
Order By: tbl_ao_col.c3
99+
-> Sort (cost=5294619.34..5297119.34 rows=20834 width=3200)
100+
Sort Key: tbl_ao_col.c2, tbl_ao_col.c3
101+
-> Redistribute Motion 48:48 (slice1; segments: 48) (cost=0.00..127928.00 rows=20834 width=3200)
102+
如果c2的数据倾斜很严重,会导致某个SEGMENT节点的数据过多。后面的计算截断可能造成OOM或者disk full。
103+
Hash Key: tbl_ao_col.c2
104+
-> Append-only Columnar Scan on tbl_ao_col (cost=0.00..107928.00 rows=20834 width=3200)
105+
Settings: optimizer=off
106+
Optimizer status: legacy query optimizer
107+
(13 rows)
108+
```
109+
110+
使用窗口函数时,Greenplum需要先按窗口中的分组对数据进行重分布,这一次重分布就可能导致严重的倾斜。
111+
112+
实际上内核层优化才是最好的解决办法,例如以上窗口函数,由于我们只需要取c2分组中c3最小的一条记录。因此也可以在每个节点先取得一条,再重分布,再算。
113+
114+
不通过修改内核,还有什么方法呢?
115+
116+
3\.1 Mapreduce任务就很好解决,Greenplum的mapreduce接口调用方法如下:
117+
118+
http://greenplum.org/docs/ref_guide/yaml_spec.html
119+
120+
3\.2 通过写PL函数也能解决。例如
121+
122+
```
123+
declare
124+
v_c2 int;
125+
v_t tbl_ao_col;
126+
begin
127+
for v_c2 in select c2 from tbl_ao_col group by c2
128+
loop -- 引入多次扫描数据的成本,其实是不划算的,还是内核解决最棒。
129+
select t into v_t from tbl_ao_col as t where c2=v_c2 order by c3 limit 1;
130+
return next v_t;
131+
end loop;
132+
end;
133+
```
134+
135+
## 小结
136+
数据倾斜的原因可能是数据存储的倾斜,QUERY执行过程中数据重分布的倾斜。
137+
138+
数据倾斜可能引入以下后果:
139+
140+
1、计算短板
141+
142+
2、oom
143+
144+
3、disk full
145+
146+
数据倾斜的解决办法:
147+
148+
1、如果是存储的倾斜,通过调整更加均匀的分布键来解决。(也可以选择使用随机分布,或者使用多列作为分布键)。
149+
150+
2、如果是QUERY造成的倾斜,Greenplum内核对group by已经做了优化,即使分组字段不是分布键,通过多阶段聚合,可以消除影响。
151+
152+
3、如果是窗口函数QUERY造成的倾斜,目前内核没有对这部分优化,首先会对窗口函数的分组字段所有数据进行重分布,如果这个分组字段数据有严重倾斜,那么会造成重分布后的某些节点数据量过大。解决办法有mapreduce或pl函数。
153+
154+
## 参考
155+
[《Greenplum 内存与负载管理最佳实践》](../201708/20170821_01.md)
156+
157+
[《Greenplum 最佳实践 - 数据分布黄金法则 - 分布列与分区的选择》](../201607/20160719_02.md)

201708/20170821_02_pic_001.jpg

16.8 KB
Loading

201708/readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
### 文章列表
22
----
3-
##### 20170821_01.md [《Greenplum 内存与负载管理最佳实践》](20170821_01.md)
3+
##### 20170821_02.md [《分布式DB中数据倾斜的原因和解法 - 阿里云HybridDB for PostgreSQL最佳实践》](20170821_02.md)
4+
##### 20170821_01.md [《Greenplum 内存与负载管理(resource queue)最佳实践》](20170821_01.md)
45
##### 20170820_03.md [《解读PostgreSQL共享存储一写多读技术(类Oracle RAC架构)》](20170820_03.md)
56
##### 20170820_02.md [《数据寻龙点穴(空间聚集分析) - 阿里云RDS PostgreSQL最佳实践》](20170820_02.md)
67
##### 20170820_01.md [《PostGIS空间索引(GiST、BRIN、R-Tree)选择、优化 - 阿里云RDS PostgreSQL最佳实践》](20170820_01.md)

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ digoal's|PostgreSQL|文章|归类
2929

3030
### 未归类文档如下
3131
----
32-
##### 201708/20170821_01.md [《Greenplum 内存与负载管理最佳实践》](201708/20170821_01.md)
32+
##### 201708/20170821_02.md [《分布式DB中数据倾斜的原因和解法 - 阿里云HybridDB for PostgreSQL最佳实践》](201708/20170821_02.md)
33+
##### 201708/20170821_01.md [《Greenplum 内存与负载管理(resource queue)最佳实践》](201708/20170821_01.md)
3334
##### 201708/20170820_03.md [《解读PostgreSQL共享存储一写多读技术(类Oracle RAC架构)》](201708/20170820_03.md)
3435
##### 201708/20170820_02.md [《数据寻龙点穴(空间聚集分析) - 阿里云RDS PostgreSQL最佳实践》](201708/20170820_02.md)
3536
##### 201708/20170820_01.md [《PostGIS空间索引(GiST、BRIN、R-Tree)选择、优化 - 阿里云RDS PostgreSQL最佳实践》](201708/20170820_01.md)

0 commit comments

Comments
 (0)