为了加速查询并满足业务需求,通常以并行执行来优化查询时间。那么,并行资源为多少才合适呢?在优化器中,并行资源量可以使用并行度(DOP:Degree of Parallel)来描述,在实际业务场景中,并行是否开启及并行度大小,根据查询的执行实际情况和业务需求以经验为基础来决定。
在人为指定并行度时,可以通过系统变量对当前会话中的所有执行查询开启并行,并指定并行度。然而,这对会话中本不需要并行加速或无需使用较高 DOP 的查询带来额外的并行执行开销,从而导致性能下降。另一方面,可以通过 hint 的方式来指定特定查询的并行度,但这需要对每一条业务查询进行单独考量,对于存在大量业务查询的情况,是不可行的。
为了解决手动指定并行度的不便和限制,查询优化器可以通过Auto DOP功能在生成查询计划时评估查询需要执行的时间,自动确定是否开启并行和开启适量的并行度。这样可以避免由于手动指定并行度而导致的性能下降。
开启 Auto DOP
优化器的 DOP 选择策略目前分为 AUTO 模式和 MANUAL 模式。AUTO 模式下优化器可以根据查询实际情况,自动选择开启并行,并确定并行度。MANUAL 模式仅能通过人为干预开启并行。
优化器的 DOP 选择策略有两种控制方式,可以通过系统变量 parallel_degree_policy 进行全局或 session 级别的 DOP 选择策略配置,也通过更高优先级的 hint 进行查询级别的 DOP 选择策略配置。具体配置方法如下:
-- 在全局级别启用 Auto DOP
set global parallel_degree_policy = AUTO;
-- 在 session 级别启用 Auto DOP
set session parallel_degree_policy = AUTO;
set parallel_degree_policy = AUTO;
-- 在全局级别禁止 Auto DOP
set global parallel_degree_policy = MANUAL;
-- 在 session 级别禁止 Auto DOP
set session parallel_degree_policy = MANUAL;
set parallel_degree_policy = MANUAL;
-- 使用 hint 在查询级别启用 Auto DOP
select /*+parallel(auto)*/ * from t1;
-- 使用 hint 在查询级别禁止 Auto DOP
select /*+parallel(manual)*/ * from t1;
select /*+parallel(8)*/ * from t1;
在 OceanBase 4.2 版本中,parallel_degree_policy 默认设置为 MANUAL。
Auto DOP 相关设置
在 Auto DOP 策略下,有两个相关的变量会影响获取的 DOP 大小。
变量 parallel_degree_limit 限制 Auto DOP 策略时允许使用的最大 DOP,parallel_degree_limit 缺省值为 0,使用缺省值时,使用下面两种方法得到的较小值限制最大 DOP:
1. 变量 parallel_servers_target 的设置值。
2. 利用租户 unit 的 min cpu 与读取表的 server 数量相乘得到限制值。
如 parallel_degree_limit = 0,parallel_servers_target = 10, min_cpu = 2, 下方查询读取的两个分区分布在两台 observer 上,则最大可用 DOP 为 min(10, 2*2) = 4
select * from t1 partition (p0, p1);
min_cpu 可以通过 select min_cpu from oceanbase.V$OB_UNITS; 查询
变量 parallel_min_scan_time_threshold 是在 Auto DOP 策略中用于计算并行度的参数,表示对基表扫描开启并行的参考执行时间。当基表扫描评估执行时间超过这个设定值时,会对基表扫描开启并行,并利用这个设定值计算一个合适的并行度。变量默认值设置为 1000,单位毫秒。通过调小 parallel_min_scan_time_threshold 的值,可以降低对基表开启并行的门限制,允许对评估执行时间更小基表扫描开启并行,对已经开启并行且数据量固定的表,也会使用更大的并行度进行扫描。
-- 设置 global/session 级别 Auto DOP 策略最大 DOP 限制
set global parallel_degree_limit = 64;
set session parallel_degree_limit = 64;
set parallel_degree_limit = 64;
-- 设置 global/session 级别 Auto DOP 策略 DOP
set global parallel_min_scan_time_threshold = 100;
set session parallel_min_scan_time_threshold = 100;
set parallel_min_scan_time_threshold = 100;
Auto DOP 与其它并行开启方式关系
对于开启并行的多种方式,优先级关系详见官网文档并行开启方式及优先级。
开启 Auto DOP 后,优化器可以对 select/delete/update/insert 等多种操作开启并行,对于 delete/update/insert 等数据维护操作,开启并行后会自动使用 PDML,不需要再对 _enable_parallel_dml 进行配置打开 PDML。
Auto DOP 使用场景
Auto DOP 可以对查询主动开启并行,但使用并行度的大小受到一些配置项的影响,在不同场景下使用 Auto DOP 需要对相关参数进行一些调整。
场景1:查询性能极致优化
当数据库没有其它查询负载时,想要利用租户下所有并行执行资源获得极致查询性能时,可以将 Auto DOP 开启并行的参考执行时间设到最低,同时不主动对 Auto DOP 使用的最大 DOP 进行限制。此时将相关参数进行以下设置:
set parallel_degree_policy = AUTO;
set parallel_degree_limit = 0;
set parallel_min_scan_time_threshold = 10;
场景2:系统性能优化
当数据库大量并发查询负载时,大量查询使用较高 DOP 会导致系统并行资源不足,导致查询队列排队等问题。为了避免大量大并行度查询对系统资源的占用,可以对查询机制性能优化中的参数进行调整:
a. 将 parallel_degree_limit 设置为小于系统 CPU 数的某个数值,限制 Auto DOP 使用的最大 DOP;
b. 将 parallel_min_scan_time_threshold 调大,整体降低大量查询使用的并行度。
如限制最大使用 DOP = 32 、对基表扫描评估时间超过20ms的查询开启并行的参数设置如下:
set parallel_degree_policy = AUTO;
set parallel_degree_limit = 32;
set parallel_min_scan_time_threshold = 20;
Auto DOP 策略下 DOP 的获取
Auto DOP 策略下首先通过一定算法确定基表扫描算子使用的 DOP(通过对不同并行度下基表扫描执行时间进行估计,综合 parallel_min_scan_time_threshold 和最大允许 DOP 得到,其它算子的 DOP 在计划生成的过程中,通过继承孩子算子的 DOP 获取。
如下方查询,表 tp1、tp2 插入一定规模数据后,使用 Auto DOP 策略,同时指定两表的连接顺序、分布式连接方法。对于表 A、B 使用 Auto DOP 策略,获取并行度为 DOP = 4、DOP = 8。两表使用 HASH HASH 的分布式连接方法后,HASH JOIN 算子的并行度通过继承得到,使用了左右两个孩子算子中较大并行度 DOP = 8。
create table tp1(c1 int, c2 int, c3 int) partition by hash(c1) partitions 4;
create table tp2(c1 int, c2 int, c3 int) partition by hash(c1) partitions 8;
explain basic
select /*+leading(a b) use_hash(a b) pq_distribute(b hash hash) */
* from tp1 a, tp2 b where a.c1 = b.c1;
+------------------------------------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------------------------------------+
| =========================================== |
| |ID|OPERATOR |NAME | |
| ------------------------------------------- |
| |0 |PX COORDINATOR | | |
| |1 | EXCHANGE OUT DISTR |:EX10002| |
| |2 | HASH JOIN | | |
| |3 | EXCHANGE IN DISTR | | |
| |4 | EXCHANGE OUT DISTR (HASH)|:EX10000| |
| |5 | PX BLOCK ITERATOR | | |
| |6 | TABLE SCAN |A | |
| |7 | EXCHANGE IN DISTR | | |
| |8 | EXCHANGE OUT DISTR (HASH)|:EX10001| |
| |9 | PX BLOCK ITERATOR | | |
| |10| TABLE SCAN |B | |
| =========================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(A.C1, A.C2, A.C3, B.C1, B.C2, B.C3)]), filter(nil), rowset=256 |
| 1 - output([INTERNAL_FUNCTION(A.C1, A.C2, A.C3, B.C1, B.C2, B.C3)]), filter(nil), rowset=256 |
| dop=8 |
| 2 - output([A.C1], [B.C1], [A.C2], [A.C3], [B.C2], [B.C3]), filter(nil), rowset=256 |
| equal_conds([A.C1 = B.C1]), other_conds(nil) |
| 3 - output([A.C1], [A.C2], [A.C3]), filter(nil), rowset=256 |
| 4 - output([A.C1], [A.C2], [A.C3]), filter(nil), rowset=256 |
| (#keys=1, [A.C1]), dop=4 |
| 5 - output([A.C1], [A.C2], [A.C3]), filter(nil), rowset=256 |
| 6 - output([A.C1], [A.C2], [A.C3]), filter(nil), rowset=256 |
| access([A.C1], [A.C2], [A.C3]), partitions(p[0-3]) |
| is_index_back=false, is_global_index=false, |
| range_key([A.__pk_increment]), range(MIN ; MAX)always true |
| 7 - output([B.C1], [B.C2], [B.C3]), filter(nil), rowset=256 |
| 8 - output([B.C1], [B.C2], [B.C3]), filter(nil), rowset=256 |
| (#keys=1, [B.C1]), dop=8 |
| 9 - output([B.C1], [B.C2], [B.C3]), filter(nil), rowset=256 |
| 10 - output([B.C1], [B.C2], [B.C3]), filter(nil), rowset=256 |
| access([B.C1], [B.C2], [B.C3]), partitions(p[0-7]) |
| is_index_back=false, is_global_index=false, |
| range_key([B.__pk_increment]), range(MIN ; MAX)always true |
+------------------------------------------------------------------------------------------------+
小结
Auto DOP 提供了对各类 DML 操作自动开启并行的能力,一定程度上解决了依赖手动调整 DOP 的局限性。
Auto DOP 以计算基表最佳并行度为基础,在计划生成过程中根据计划形态不同产生各算子使用的并行度。使用这种策略能够得到相对稳定可靠的并行度,但对于一些特定场景开启的并行度可能偏小,如中间结果集相对基表扫描的数据量急剧膨胀、存在特定性能瓶颈等。
目前 Auto DOP 不具备系统负载感知、动态调整或反馈调整 DOP 的能力,因此使用 Auto DOP 时需要关注数据库的业务场景,针对查询性能极致优化或系统级性能优化对 Auto DOP 几个相关配置项进行调整。