并行技术(Symmetric Multi-Processing, 简称SMP)是一种利用计算机多核CPU架构实现的并行多线程计算的技术,通过充分利用CPU资源来提高查询性能。在复杂查询场景中,单个查询的执行较长,系统并发度低。南大通用GBase 8c通过SMP并行执行技术实现算子级的并行,能够有效减少查询执行时间,提升查询性能及资源利用率。SMP并行技术的整体实现思想是对于能够并行的查询算子,将数据分片,启动若干个工作线程分别计算,最后将结果汇总,返回前端。SMP并行执行增加数据交互算子(Stream),实现多个工作线程之间的数据交互,确保查询的正确性,完成整体的查询。

算子说明

执行计划中支持并行的算子包括:

  • Scan:支持行存普通表和行存分区表顺序扫描、列存普通表和列存分区表顺序扫描。
  • Join:HashJoin、NestLoop
  • Agg:HashAgg、SortAgg、PlainAgg、WindowAgg(只支持partition by,不支持order by)。
  • Stream:Local Redistribute、Local Broadcast
  • 其他:Result、Subqueryscan、Unique、Material、Setop、Append、VectoRow

SMP特有算子:为了实现并行,新增了并行线程间的数据交换Stream算子供SMP特性使用。这些新增的算子可以看做Stream算子的子类。

  • Local Gather:实现实例内部并行线程的数据汇总。
  • Local Redistribute:在实例内部各线程之间,按照分布键进行数据重分布。
  • Local Broadcast:将数据广播到实例内部的每个线程。
  • Local RoundRobin:在实例内部各线程之间实现数据轮询分发。

执行计划中不支持并行的算子包括:

  • 索引扫描不支持并行执行。
  • MergeJoin不支持并行执行。
  • WindowAgg order by不支持并行执行。
  • cursor不支持并行执行。
  • 存储过程和函数内的查询不支持并行执行。
  • 不支持子查询subplan和initplan的并行,以及包含子查询的算子的并行。
  • 查询语句中带有median操作的查询不支持并行执行。
  • 带全局临时表的查询不支持并行执行。
  • 物化视图的更新不支持并行执行。

SMP前置条件

SMP架构是一种利用富余资源来换取时间的方案,计划并行之后必定会引起资源消耗的增加,包括CPU、内存、I/O等资源的消耗都会出现明显的增长,而且随着并行度的增大,资源消耗也随之增大。当上述资源成为瓶颈的情况下,SMP无法提升性能,反而可能导致数据库实例整体性能的劣化,所以在开启SMP之前需要对数据库服务器资源进行充分评估,包括:

  • CPU:当系统CPU利用率不高的情况下,利用SMP并行架构能够更充分地利用系统CPU资源,提升系统性能。但当数据库服务器的CPU核数较少,CPU利用率已经比较高的情况下,如果打开SMP并行,不仅性能提升不明显,反而可能因为多线程间的资源竞争而导致性能劣化。
  • 内存:查询并行后会导致内存使用量的增长,但每个算子使用内存上限仍受到work_mem等参数的限制。假设work_mem为4GB,并行度为2,那么每个并行线程所分到的内存上限为2GB。在work_mem较小或者系统内存不充裕的情况下,使用SMP并行后,可能出现数据下盘,导致查询性能劣化的问题。
  • I/O:要实现并行扫描必定会增加I/O的资源消耗,因此只有在I/O资源充足的情况下,并行扫描才能够提高扫描性能。

启用SMP

(1)本窗口生效

使用set query_dop = num; 可以设置并行执行在本窗口生效;

test=# set query_dop = 4;
SET
test=# explain select age,count(*) from stu group by age;

(2)指定SQL生效

对执行SQL添加hint,可以制定对某语句开启并行执行

test=# explain  select/*+set(query_dop 2)*/ age,count(*) from stu group by age ;

(3)集群全局生效

--3.0.0执行
gs_guc reload -Z coordinator -N all -I all -c "query_dop=4"
gs_guc reload -Z datanode -N all -I all -c "query_dop=4"
gs_guc reload -Z gtm -N all -I all -c "query_dop=4"
--5.0.0执行
gs_guc reload -N all -I all -h "query_dop=4"