Skip to content

Commit cbd34de

Browse files
digoal zhoudigoal zhou
authored andcommitted
new doc
1 parent 86a70e5 commit cbd34de

File tree

6 files changed

+175
-1
lines changed

6 files changed

+175
-1
lines changed

202112/20211224_04.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ postgres=# explain select * from a where substring(col,1,5) = 'abcde';
5656
- 2、不管是谁、在什么时间、在什么空间调用这个函数, 虽然函数的输入参数不变, 但是结果依旧有可能变化.
5757

5858
因此有了函数稳定性的概念(详见create function语法), PostgreSQL的3中函数稳定性状态:
59-
- immutable, 任何人任何时候调用它, 输入参数不变, 结果就不变. 如果输入参数是常量, 优化器会在生成执行计划前就把这个函数的结果算出来.
59+
- immutable, 任何人任何时候调用它, 输入参数不变, 结果就不变. 如果输入参数是常量, 优化器会在生成执行计划前就把这个函数的结果算出来. (即使重启实例,即使修改数据库的GUC参数都不例外, 极其稳定)
6060
- 可以用来创建表达式索引
6161
- 如果作为where条件(例如 `where id > func_immu(常数)`), 允许使用索引扫描.
6262
- stable, 在同一个事务中, 多次调用, 输入参数不变, 结果就不变.

202201/20220120_01.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
## 一起学PolarDB - 第20期 - 为什么GIS时空查询即耗CPU又费IO?
2+
3+
### 作者
4+
digoal
5+
6+
### 日期
7+
2022-01-20
8+
9+
### 标签
10+
PostgreSQL , PolarDB
11+
12+
----
13+
14+
## 背景
15+
懂PostgreSQL, 学PolarDB不难, 就好像有九阳神功护体, 可以快速融会贯通.
16+
对于DBA只要学会PolarDB精髓即可.
17+
对于开发者来说不需要学习, 使用PolarDB和PostgreSQL一样.
18+
19+
#### 为什么GIS时空查询即耗CPU又费IO?
20+
比较典型的时空查询包括:
21+
- 搜索附近的对象. (打车、订餐、交友、酒店、加油站等POI搜索)
22+
- 通过 GiST 索引可以支持空间排序 , 但是加入距离条件后需要recheck, 如果再加入limit 且符合条件的数据不足会导致性能骤变. 导致cpu和io浪费. 优化方法如下:
23+
- [《PostgreSQL PostGIS 的5种空间距离排序(knn)算法》](../201806/20180605_02.md)
24+
- [《GIS附近查找性能优化 - PostGIS long lat geometry distance search tuning using gist knn function》](../201308/20130806_01.md)
25+
- [《PostgreSQL GiST Order by 距离 + 距离范围判定 + limit 骤变优化与背景原因》](../201912/20191218_02.md)
26+
- 输入一个空间多边形, 进行包含查询. (例如 刑侦、热力、政务、车联网等按输入的动态或静态多边形查找在这个多边形内的对象)
27+
- 由于索引的root和branch page的entry都是bound box的, 与实际存储的多边形相比, 存在空间放大的问题, 搜索时会出现大了recheck filter rows. 导致cpu和io浪费. 优化方法如下:
28+
- [《PostgreSQL 空间切割(st_split, ST_Subdivide)功能扩展 - 空间对象网格化 (多边形GiST优化)》](../201710/20171005_01.md)
29+
- [《PostgreSQL 空间st_contains,st_within空间包含搜索优化 - 降IO和降CPU(bound box) (多边形GiST优化)》](../201710/20171004_01.md)
30+
- 路径规划 (例如网约车调度、快递调度、导航等)
31+
- 需要大量数据的叠加时空计算, 耗费IO和CPU较多.
32+
- 轨迹碰撞 (典型的刑侦场景、舆情场景例如新冠疫情下, 快速找出和病毒携带者轨迹可能有近距离接触的人群)
33+
- 需要大量数据的叠加时空计算, 耗费IO和CPU较多.
34+
- 时空范围内的对象流量、停留时间等维度统计 (促销复盘、热力图统计等场景)
35+
- 需要大量数据的时空统计计算, 耗费IO和CPU较多.
36+
37+
社区版本:
38+
通过以上的优化方法后, 如果还要提升性能怎么办? 用并行scan?
39+
40+
可是目前只有btree索引支持并行scan:
41+
42+
```
43+
grep -r amcanparallel *
44+
brin/brin.c: amroutine->amcanparallel = false;
45+
gin/ginutil.c: amroutine->amcanparallel = false;
46+
gist/gist.c: amroutine->amcanparallel = false;
47+
hash/hash.c: amroutine->amcanparallel = false;
48+
nbtree/nbtree.c: amroutine->amcanparallel = true;
49+
spgist/spgutils.c: amroutine->amcanparallel = false;
50+
51+
52+
53+
/*
54+
* API struct for an index AM. Note this must be stored in a single palloc'd
55+
* chunk of memory.
56+
*/
57+
typedef struct IndexAmRoutine
58+
{
59+
...
60+
/* does AM support parallel scan? */
61+
bool amcanparallel;
62+
/* does AM support columns included with clause INCLUDE? */
63+
bool amcaninclude;
64+
/* does AM use maintenance_work_mem? */
65+
bool amusemaintenanceworkmem;
66+
/* OR of parallel vacuum flags. See vacuum.h for flags. */
67+
uint8 amparallelvacuumoptions;
68+
69+
```
70+
71+
为了使用并行计算, 需要将表进行分区, 通过parallel table scan (enable_parallel_append)来实现多分区并行加速.
72+
但是最多也只能用到单个实例的能力(受制于单实例的cpu和IO能力), 无法多实例并行.
73+
74+
分区可能引入一些其他的问题: [《每天5分钟,PG聊通透 - 系列1 - 热门问题 - 链接、驱动、SQL - 第20期 - 为什么分区表的分区过多会导致性能下降?》](../202112/20211224_01.md)
75+
- 分区是偏静态的(将来要调整分区规则, 分区边界的话需要DDL操作),
76+
- PG社区版本目前没有全局索引, 全局约束. 如果有这方面的需求就不能分区.
77+
78+
截止到目前的PG版本(14), 分区过多也会有一些问题:
79+
80+
问题1: 分区过多, 对于一些老版本的PG, 优化器在生成path后才会裁剪分区, 分区过多会使得生成执行计划非常耗时. 对于短平快的SQL, 性能损耗尤为突出.
81+
- 老的PG版本可能使用pg_pathman进行此类优化(裁剪优化)
82+
83+
问题2: relcache 缓存暴增, 老版本的PG会缓存所有的分区元数据. 即使是优化后的PG新版本, 如果业务使用了长连接, 假使每个会话在会话的整个生命周期内访问过每个子分区的话, 同样会导致relcache占用内存过多, 使得每个会话占有大量内存. 甚至触发OOM.
84+
85+
问题3: 当SQL没有输入分区字段作为条件时, 需要访问所有分区, 分区过多会导致执行计划时间超长. 同时可能某些更优的访问路径就无法支持(例如某些情况下hashagg, hashjoin, merge join等可能无法支持)
86+
- 目前未支持分区表全局索引, 所以按非分区字段排序需要访问所有分区, 使用merge sort方式进行优化.
87+
- 不含分区字段的过滤, 无法裁剪分区, 即使有索引也需要访问所有分区, 需要访问更多数据块(每个本地索引的meta page, branch page, leaf page).
88+
89+
PolarDB:
90+
91+
1、优化器支持GiST并行扫描.
92+
93+
![pic](20220120_01_pic_001.png)
94+
95+
2、优化器支持多节点(RW+RO)并行扫描
96+
97+
```
98+
数据量:40000 万,500 GB
99+
规格:5 个只读节点,每个节点规格为 16 核 CPU、128 GB 内存
100+
性能:
101+
随 CPU 数目线性提升, 共 80 核 CPU 时,提升71 倍
102+
```
103+
104+
![pic](20220120_01_pic_002.png)
105+
106+
本期问题1:
107+
时空查询为什么即使使用GiST索引依旧存在CPU和IO放大的问题?
108+
- a. GiST的索引root,branch节点采用bound box作为边界, 所以搜索到叶子结点后, 还需要做一些 recheck 计算
109+
- b. 需要遍历整个GiST索引
110+
- c. GiST 索引是lossy类型的索引
111+
- d. GiST 索引存在页面膨胀
112+
113+
答案:
114+
- a
115+
116+
解释:
117+
- 参考本文内容
118+
119+
本期问题2:
120+
PostgreSQL 14社区版支持并行的索引扫描方法有哪些?
121+
- a. GiST
122+
- b. SP-GiST
123+
- c. btree
124+
- d. BRIN
125+
126+
答案:
127+
- c
128+
129+
解释:
130+
- 参考本文内容
131+
132+
本期问题3:
133+
PolarDB 对时空扫描做了哪些优化?
134+
- a. GiST 索引支持并行扫描
135+
- b. 不使用bound box来作为索引的内部key value边界
136+
- c. 支持将RW和RO节点列入并行扫描, 执行一条SQL可以同时用到多个计算节点
137+
- d. 支持GiST的精准过滤, 在叶子结点不需要recheck 计算
138+
139+
答案:
140+
- ac
141+
142+
解释:
143+
- 参考本文内容
144+
145+
本期问题4:
146+
当时空扫描存在cpu和io放大时, 业务上如何优化的性价比最高?
147+
- a. 切分输入条件, 尽量缩小bound box的覆盖范围
148+
- b. 使用函数或递归查询, 迅速检测到limit的边界条件, 防止符合条件的记录数不足limit条数时需要扫描整个gist索引的内容
149+
- c. 采用并行计算, 暴力加速
150+
- d. 采用分区表
151+
152+
答案:
153+
- ab
154+
155+
解释:
156+
- 参考本文内容
157+
158+
159+
#### [期望 PostgreSQL 增加什么功能?](https://github.com/digoal/blog/issues/76 "269ac3d1c492e938c0191101c7238216")
160+
161+
162+
#### [PolarDB for PostgreSQL云原生分布式开源数据库](https://github.com/ApsaraDB/PolarDB-for-PostgreSQL "57258f76c37864c6e6d23383d05714ea")
163+
164+
165+
#### [PostgreSQL 解决方案集合](https://yq.aliyun.com/topic/118 "40cff096e9ed7122c512b35d8561d9c8")
166+
167+
168+
#### [德哥 / digoal's github - 公益是一辈子的事.](https://github.com/digoal/blog/blob/master/README.md "22709685feb7cab07d30f30387f0a9ae")
169+
170+
171+
![digoal's wechat](../pic/digoal_weixin.jpg "f7ad92eeba24523fd47a6e1a0e691b59")
172+

202201/20220120_01_pic_001.png

342 KB
Loading

202201/20220120_01_pic_002.png

84.6 KB
Loading

202201/readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### 文章列表
44
----
5+
##### 20220120_01.md [《一起学PolarDB - 第20期 - 为什么GIS时空查询即耗CPU又费IO?》](20220120_01.md)
56
##### 20220119_02.md [《一起学PolarDB - 第19期 - 为什么做检查点会导致性能抖动?》](20220119_02.md)
67
##### 20220119_01.md [《PostgreSQL 15 preview - pg_basebackup 增强, 支持扩展COPY协议》](20220119_01.md)
78
##### 20220118_05.md [《一起学PolarDB - 第18期 - 为什么创建索引慢?》](20220118_05.md)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ digoal's|PostgreSQL|文章|归类
8787

8888
### 所有文档如下
8989
----
90+
##### 202201/20220120_01.md [《一起学PolarDB - 第20期 - 为什么GIS时空查询即耗CPU又费IO?》](202201/20220120_01.md)
9091
##### 202201/20220119_02.md [《一起学PolarDB - 第19期 - 为什么做检查点会导致性能抖动?》](202201/20220119_02.md)
9192
##### 202201/20220119_01.md [《PostgreSQL 15 preview - pg_basebackup 增强, 支持扩展COPY协议》](202201/20220119_01.md)
9293
##### 202201/20220118_05.md [《一起学PolarDB - 第18期 - 为什么创建索引慢?》](202201/20220118_05.md)

0 commit comments

Comments
 (0)