为了最大程度降低 PX 使用难度,OceanBase 3.1 版起,parallel_max_servers 参数废弃。
用户只需用好 parallel_servers_target 即可。
target 的用途
用一个酒吧的例子来粗略理解下 parallel_servers_target
的意思:
target 先生开了一个酒吧。来这个酒吧里喝酒的都是一群一群的人。酒吧最多容纳100个人 (parallel_servers_target = 100
)。
如果酒吧里面一个人都没有(比如刚刚开门),那么来的第一群人总是让他们进去,并且:
- 如果他们的人数多于100人,则放100人进去。
- 如果小于100人,例如 30 个人( /*+ parallel(30) */),则有多少放进去多少。
如果酒吧里已经有人在喝酒了,那么新来的一群人,target 会数一数:
- 如果进去后酒吧装不下,则不让他们进去。
- 反之,只要装得下,就放进去。
通过这种方式,target 先生可以保证:
- 酒吧不会空闲:即使来的每一群人都超过100人,他也有生意做。
- 酒吧不会太挤:他的策略可以保证酒吧里的人总是不会超过100人。
真实线程数计算
最简单的 select 场景
select /*+ parallel(30) */ * from t1;
假设 parallel_servers_target = 100
, /*+ parallel(30) */,那么会启动 30 个线程来执行 SQL。
多个 dfo 的复杂场景
select /*+ parallel(30) / count() from t1, t2 group by t1.c1, t2.c1;
假设 parallel_servers_target = 100
, /*+ parallel(30) */,那么一般来说会启动 60 个线程来执行 SQL。下面的 dfo 使用 30 个线程,上面的 dfo 使用 30 个线程,他们之间形成 producer-consumer 关系。
target 相对较小的场景
select /*+ parallel(30) */ * from t1;
假设 parallel_servers_target = 10
, /*+ parallel(30) */,那么会启动 10 个线程来执行 SQL,而不是启动 30 个线程来执行 SQL!
复杂 SQL里,假设 parallel_servers_target = 10
, /*+ parallel(30) */,那么会启动 10 个线程来执行 SQL,并且下面的 dfo 使用 5 个线程,上面的 dfo 使用 5 个线程(并不是每个 dfo 使用 10 个线程,没那么多资源)
更特殊的场景
- 某些计划形态,会同时调度 3 个 dfo 起来,假设
parallel_servers_target = 12
, /*+ parallel(30) */,那么 dfo1 使用 4 个线程,dfo2 使用 4 个线程,dfo3 使用 4 个线程。 - 某些 dfo 只能用一个线程执行(计划上会有 local 标记,如2阶段聚集计算的第二阶段),线程的分配就更复杂了
复杂例子
update /*+ parallel(10) enable_parallel_dml */ lyqtest1 t1 set t1.num = (select num from lyqtest t2 where t2.num=3) + t1.num where pk_id < (