Skip to content

Latest commit

 

History

History
183 lines (128 loc) · 8.62 KB

20220120_01.md

File metadata and controls

183 lines (128 loc) · 8.62 KB

一起学PolarDB - 第20期 - 为什么GIS时空查询即耗CPU又费IO?

作者

digoal

日期

2022-01-20

标签

PostgreSQL , PolarDB


背景

懂PostgreSQL, 学PolarDB不难, 就好像有九阳神功护体, 可以快速融会贯通.
对于DBA只要学会PolarDB精髓即可.
对于开发者来说不需要学习, 使用PolarDB和PostgreSQL一样.

为什么GIS时空查询即耗CPU又费IO?

https://www.bilibili.com/video/BV1KF411E7uF/

比较典型的时空查询包括:

社区版本:
通过以上的优化方法后, 如果还要提升性能怎么办? 用并行scan?

可是目前只有btree索引支持并行scan:

grep -r amcanparallel *  
brin/brin.c:	amroutine->amcanparallel = false;  
gin/ginutil.c:	amroutine->amcanparallel = false;  
gist/gist.c:	amroutine->amcanparallel = false;  
hash/hash.c:	amroutine->amcanparallel = false;  
nbtree/nbtree.c:	amroutine->amcanparallel = true;  
spgist/spgutils.c:	amroutine->amcanparallel = false;  
  
  
  
/*  
 * API struct for an index AM.  Note this must be stored in a single palloc'd  
 * chunk of memory.  
 */  
typedef struct IndexAmRoutine  
{  
...  
        /* does AM support parallel scan? */  
        bool            amcanparallel;  
        /* does AM support columns included with clause INCLUDE? */  
        bool            amcaninclude;  
        /* does AM use maintenance_work_mem? */  
        bool            amusemaintenanceworkmem;  
        /* OR of parallel vacuum flags.  See vacuum.h for flags. */  
        uint8           amparallelvacuumoptions;  
  

为了使用并行计算, 需要将表进行分区, 通过parallel table scan (enable_parallel_append)来实现多分区并行加速.
但是最多也只能用到单个实例的能力(受制于单实例的cpu和IO能力), 无法多实例并行.

分区可能引入一些其他的问题: 《每天5分钟,PG聊通透 - 系列1 - 热门问题 - 链接、驱动、SQL - 第20期 - 为什么分区表的分区过多会导致性能下降?》

  • 分区是偏静态的(将来要调整分区规则, 分区边界的话需要DDL操作),
  • PG社区版本目前没有全局索引, 全局约束. 如果有这方面的需求就不能分区.

截止到目前的PG版本(14), 分区过多也会有一些问题:

问题1: 分区过多, 对于一些老版本的PG, 优化器在生成path后才会裁剪分区, 分区过多会使得生成执行计划非常耗时. 对于短平快的SQL, 性能损耗尤为突出.

  • 老的PG版本可能使用pg_pathman进行此类优化(裁剪优化)

问题2: relcache 缓存暴增, 老版本的PG会缓存所有的分区元数据. 即使是优化后的PG新版本, 如果业务使用了长连接, 假使每个会话在会话的整个生命周期内访问过每个子分区的话, 同样会导致relcache占用内存过多, 使得每个会话占有大量内存. 甚至触发OOM.

问题3: 当SQL没有输入分区字段作为条件时, 需要访问所有分区, 分区过多会导致执行计划时间超长. 同时可能某些更优的访问路径就无法支持(例如某些情况下hashagg, hashjoin, merge join等可能无法支持)

  • 目前未支持分区表全局索引, 所以按非分区字段排序需要访问所有分区, 使用merge sort方式进行优化.
  • 不含分区字段的过滤, 无法裁剪分区, 即使有索引也需要访问所有分区, 需要访问更多数据块(每个本地索引的meta page, branch page, leaf page).

PolarDB:

1、优化器支持GiST并行扫描.

pic

2、优化器支持多节点(RW+RO)并行扫描

数据量:40000 万,500 GB  
规格:5 个只读节点,每个节点规格为 16 核 CPU、128 GB 内存  
性能:  
随 CPU 数目线性提升, 共 80 核 CPU 时,提升71 倍  

pic

本期问题1:
时空查询为什么即使使用GiST索引依旧存在CPU和IO放大的问题?

  • a. GiST的索引root,branch节点采用bound box作为边界, 所以搜索到叶子结点后, 还需要做一些 recheck 计算
  • b. 需要遍历整个GiST索引
  • c. GiST 索引是lossy类型的索引
  • d. GiST 索引存在页面膨胀

答案:

  • a

解释:

  • 参考本文内容

本期问题2:
PostgreSQL 14社区版支持并行的索引扫描方法有哪些?

  • a. GiST
  • b. SP-GiST
  • c. btree
  • d. BRIN

答案:

  • c

解释:

  • 参考本文内容

本期问题3:
PolarDB 对时空扫描做了哪些优化?

  • a. GiST 索引支持并行扫描
  • b. 不使用bound box来作为索引的内部key value边界
  • c. 支持将RW和RO节点列入并行扫描, 执行一条SQL可以同时用到多个计算节点
  • d. 支持GiST的精准过滤, 在叶子结点不需要recheck 计算

答案:

  • ac

解释:

  • 参考本文内容

本期问题4:
当时空扫描存在cpu和io放大时, 业务上如何优化的性价比最高?

  • a. 切分输入条件, 尽量缩小bound box的覆盖范围
  • b. 使用函数或递归查询, 迅速检测到limit的边界条件, 防止符合条件的记录数不足limit条数时需要扫描整个gist索引的内容
  • c. 采用并行计算, 暴力加速
  • d. 采用分区表

答案:

  • ab

解释:

  • 参考本文内容

digoal's wechat