并行执行的4种类别——《OceanBase 并行执行》系列 4

OceanBase 支持多种类型语句的并行执行。在本篇博客中,我们将根据并行执行的不同类别,分别详细阐述:并行查询、并行数据操作语言(DML)、并行数据定义语言(DDL)以及并行 LOAD DATA 。

《并行执行系列》并行执行系列的内容分为七篇博客,本篇是其中的第四篇。

并行执行概念
如何手动设置并行度
并行执行线程资源管理方式

4.1 并行查询

你可以在下面几种场景里使用并行查询:

  • select 语句,以及 select 子查询
  • DML 语句(INSERT,UPDATE,DELETE)的查询部分
  • 外表查询

并行查询的决策分为两部分: 

  1. 决定走并行查询。如果查询中使用了 PARALLEL HINT,SESSION 上开启了并行查询,或TABLE 属性指定了并行,那么将会开启并行查询。
  2. 决定并行度。并行查询中,每个 DFO 的并行度可以不一样。
    • 对于基表扫描或索引扫描 DFO,其并行度由 PARALLEL HINT、SESSION 并行属性,或TABLE 属性来决定。
    • 对于基表扫描或索引扫描 DFO,如果运行时检测到它访问的数据不足一个宏块,那么它的运行时并发度会被局部自动降低。
    • 对于 JOIN 等中间节点,其 DFO 并行度继承左孩子 DFO 的并行度。
    • 部分 DFO 不允许并行执行(如计算 ROWNUM 的节点),那么他们的并行度会被强制设为 1。

4.2 并行 DML

大部分场景下,可以使用并行 DML (Parallel DML,简称 PDML)加速数据导入、更新、删除操作。

4.2.1 DML 并行度

DML 的并行度和查询部分的并行度一致。开启并行 DML 时,查询部分总是自动开启并行。读出的数据会根据待更新表的分区位置做重分布,然后由多个线程并行 DML,每个线程负责若干个分区。

并行度和目标表的分区数之间有倍数关系时,一般可以达到最佳性能。当并发度高于分区数时,会有多个线程处理同一个分区的数据;当并发度低于分区数时,单个线程可能处理多个分区的数据,并且每个线程处理的分区不重合。当并行度大于目标表分区数时,建议并行度是分区数的整数倍。

一般来说,同时向一个分区插入数据的线程数不要超过 4 个,超过这个值后扩展性并不好,日志同步会成为瓶颈,另外还有一些分区级别的锁同步开销。当并行度小于目标表分区数时,建议分区数是并行度的整数倍。这样,每个线程处理的分区数差不多,可以避免插入工作量倾斜。

4.2.2 索引表处理策略

并行 DML 支持自动维护索引表。

当索引表为本地索引时,并行 DML 在更新主表时,存储层会自动维护本地索引。

当索引表为全局索引时,并行 DML 框架会生成特定的计划来维护全局索引。假设有两个全局索引,处理流程如下:

  1. 首先,会用 DFO1 更新主表;
  2. 然后,DFO1 将全局索引1、全局索引2需要的数据发给 DFO2,用 DFO2 更新全局索引表1;
  3. 最后,DFO2 将全局索2引需要的数据发给 DFO3,用 DFO3 更新全局索引表2。

1705634034

以上策略对所有 INSERT、DELETE、UPDATE 语句有效,对于 MERGE 语句,处理方式略有不同,所有的索引维护操作会集中到一个 DFO 中处理,如下图所示:

  1. 首先,会用 DFO1 更新主表;
  2. 然后,DFO1 将全局索引1、全局索引2需要的数据发给 DFO2,DFO2 内部会逐个完成全部全局索引的维护操作。

1705634043

4.2.3 更新分区键的处理策略

对于 UPDATE 语句来说,当主表或全局索引表的分区键被更新时,需要把旧数据从旧分区中删除,然后把新数据插入到新分区中。这个过程通常被称作 row movement。

当发生 row movement 时,需要将 UPDATE 操作拆分成两步操作:先 DELETE,然后 INSERT。具体地,会将出现 row movement 的 UPDATE DFO 拆分成两个 DFO,第一个 DFO 负责 DELETE,第二个 DFO 负责 INSERT。并且,为了避免主键冲突,必须确保 DELETE DFO 完全执行完成后才能开始执行 INSERT DFO。

4.2.4 事务处理

OceanBase 并行 DML 和普通 DML 语句一样,完全支持事务处理。并行 DML 语句可以和其它查询语句一起出现在同一个事务中,执行完成并行 DML 语句后无需立即提交事务,就可以在后继的查询语句中读取到 DML 语句的结果。

在 OBServer v4.1 版本之前,当并行 DML 执行时间超长时,需要给租户配置项 undo retention 设置合适的值,否则可能发生 -4138 (OB_SNAPSHOT_DISCARDED) 错误,导致 SQL 在内部反复重试,直至超时。undo retention 字面意思是 Undo 的保留位点,即从当前时间回溯多长时间的 Undo 日志是保留下来的。对于 OceanBase 数据库来说,是将该时段的所有数据多版本保留下来。当并行 DML 执行时间超过 undo retention 设定的时间时,多版本数据可能被淘汰,当 DML 中的任何后继操作试图访问淘汰的多版本数据时,就会触发 OB_SNAPSHOT_DISCARDED 报错。undo retention 的默认值是 30 分钟,这意味着在默认情况下,如果并行 DML 语句 30 分钟内不能执行完成,无论语句的超时时间设定为多少,语句都可能执行超时并报错。一般来说,如果业务中的最长并行 DML 的执行时间为 2h 时, undo retention 可以设置为 2.5h。undo retention 不能随意设置为极大值,那会导致多版本数据无法回收,打爆磁盘。

从 OBServer v4.1 版本起,并行 DML 的执行不再依赖 undo retention 设定。多版本数据会根据事务版本号回收,只要事务还活跃,事务对应的版本号能读到的内容就不会回收。不过,数据盘满的场景是例外,此时还是会强行回收多版本数据,并行 DML 会收到 OB_SNAPSHOT_DISCARDED 报错,并自动重试整个 SQL。

4.2.5 旁路导入

当内存空间不足时,并行 DML 容易报告内存不足错误。没有走旁路导入路径的并行 DML,数据首先会写入 Memtable,然后通过转储、合并写入磁盘。因为并行 DML 写入数据到 Memtable 的速度极快,当写入速度快过转储速度时,内存就会不断增长,最终触发内存不足报错。

为了解决这个问题,OceanBase v4.1 的存储层提供了旁路导入功能。当并行 DML 使用旁路导入功能执行 INSERT 语句时,数据会绕过 Memtable 直接写入磁盘,不仅避免了内存不足的问题,而且还能提升数据导入性能。

用户通过 APPEND HINT 开启旁路导入功能。旁路导入开始前,要求提交上一个事务,并且设置 autocommit = 1。在 v4.2 版本中,旁路导入功能必须配合并行 DML 才能正常工作,如果没有通过 HINT 或 session 开启并行 DML,则旁路导入的 HINT 会被自动忽略。语法示例如下:

set autocommit = 1;
insert /*+ append enable_parallel_dml parallel(3) */ into t1 select * from t2;

预计在未来版本中,旁路导入功能会放松对事务的要求,可以出现在事务中的任意位置。

4.2.6 无法并行的 DML 操作

为了保证正确的 DML 语义,如下场景中,查询部分可以并行,但 DML 部分无法并行:

  • 如果目标表包含 local unique index,则 DML 部分不可并行,查询部分依然可以并行
  • INSERT ON DUPLICATE KEY UPDATE 语句的 DML 部分不可并行
  • 如果目标表包含 Trigger、外键,则 DML 部分不可并行
  • 如果 MERGE INTO 语句的目标表中包含 global unique index,则 DML 部分不可并行
  • 如果 DML 启用了 IGNORE 模式,则 DML 部分不可并行

如果发现 DML 没有走并行,可以通过 explain extended 来查看 Note 字段,确定未走并行的原因。

4.2.7 Row Movement 操作

当更新分区表的分区键时,可能使数据从一个分区搬迁到另一个分区。在 Oracle 模式下通过下面的命令可以禁止数据跨分区搬迁:

create table t1 (c1 int primary key, c2 int) partition by hash(c1) partitions 3;
alter table t1 disable row movement;

OceanBase(TEST@TEST)>update t1 set c1 = c1 + 100000000;
ORA-14402: updating partition key column would cause a partition change

但是,并行 DML 会忽略表的 row movement 属性,总是允许更新分区键。

4.3 并行 DDL

支持并行执行的 DDL 语句包括:

  • CREATE TABLE AS SELECT
  • ALTER TABLE
  • CREATE INDEX

4.3.0 原理

所有并行 DDL 都是通过特定的 Parallel DML 完成。例如,创建索引本质是创建一个索引空表,然后并行地从主表查询出索引列数据,最后并行地插入到索引表中。

4.3.1 通过 HINT 指定并行度

目前(v4.2)仅 CREATE INDEX 语句支持通过 PARALLEL HINT 开启并行,其余 DDL 都只支持 SESSION 变量和 TABLE PARALLEL 属性来开启。

CREATE /*+ PARALLEL(3) */ INDEX IDX ON T1(C2);

4.3.2 通过 SESSION 变量指定并行度

上述所有 DDL 语句都支持通过 SESSION 变量来指定并行度。指定并行度后,该 SESSION 上的所有 DDL 都自动按照该并行度并行执行,并且查询部分和修改部分都使用相同的并行度。

SET _FORCE_PARALLEL_DDL_DOP = 3;
CREATE TABLE T1 (C1 int, C2 int, C3 int, C4 int);
CREATE INDEX IDX ON T1(C2);
-- v4.2 中,CREATE TABLE AS SELECT 开并行,
-- 用的是 “SET _FORCE_PARALLEL_DML_DOP”
-- 而不是 “SET _FORCE_PARALLEL_DDL_DOP”
-- 后继版本可能会修改成后者
SET _FORCE_PARALLEL_DML_DOP = 3;
CREATE TABLE T1 (C1 int, C2 int, C3 int, C4 int);
CREATE TABLE T2 AS SELECT * FROM T1;

4.3.3 通过表 PARALLEL 属性指定并行度

本节内容实测并没有走并行,需要跟进是否符合设计。验证方法:

select plan_operation, count(*) threads from oceanbase.gv$sql_plan_monitor where trace_id = last_trace_id() group by plan_line_id, plan_operation order by plan_line_id;

DDL 相关表上有 PARALLEL 属性时,可以使用 SET 语句设定 SESSION 变量来开启并行执行。例如:

SET _ENABLE_PARALLEL_DDL = 1;
CREATE TABLE T1 (C1 int, C2 int, C3 int, C4 int) PARALLEL = 3;
CREATE INDEX IDX ON T1(C2) PARALLEL = 2;
-- v4.2 中,CREATE TABLE AS SELECT 开并行,
-- 用的是 “SET _ENABLE_PARALLEL_DML”
-- 而不是 “SET _ENABLE_PARALLEL_DDL”
-- 后继版本可能会修改成后者
SET _ENABLE_PARALLEL_DML = 1;
CREATE TABLE T1 (C1 int, C2 int, C3 int, C4 int) PARALLEL = 3;
CREATE TABLE T2 PARALLEL 2 AS SELECT * FROM T1;

4.3.4 优先级

如果同时指定了 PARALLEL HINT、FORCE SESSION PARALLEL、表级 PARALLEL 属性中的两个或多个,那么它们的优先级如下:

PARALLEL HINT 优先级 > FORCE SESSION PARALLEL 优先级 > 表 PARALLEL 属性优先级

4.3.5 旁路导入

CREATE INDEX 语句无论是否开启并行,总是会走旁路导入(Direct Write,Bypass memtable)。

CREATE TABLE AS SELECT 语句目前(v4.2)还不支持旁路导入功能,如果数据量比较大,建议先建立空表,然后使用并行 DML 旁路导入模式并行插入。

4.4 并行 LOAD DATA

LOAD DATA 的实现不是基于并行 DML,它的实现方式是:先用多个线程并行切分 csv 文件,拼成多个 insert 语句,然后用一定的并发度分发执行这些 insert 语句。

LOAD DATA /*+ parallel(2) */ infile "test.csv" INTO TABLE t1 FIELDS TERMINATED BY ',' ENCLOSED BY '"';

上述语句中,PARALLEL 选项指定加载数据的并行度,如果没有指定 PARALLEL HINT,则默认以 PARALLEL 为 4 来并行执行 LOAD DATA。 PARALLEL 建议取值范围是 [0, 租户的最大CPU数]。

4.5 局部无法并行的场景

  • 最顶层 DFO 无需并行,它负责和客户端交互,以及执行最顶层无需并行的部分操作,如 LIMIT、PX COORDINATOR 等
  • 包含 TABLE UDF 时,含该 UDF 的 DFO 只能串行执行,其余部分依然可以并行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/611425.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker部署Metabase

文章目录 Docker安装MetabaseCentOS7安装Docker获取最新的 Docker 镜像启动Metabase容器在Metabase初始化时查看日志访问Metabase Metabase 的 ClickHouse 驱动程序安装环境简介删除容器创建容器下载click house驱动放入驱动重启容器将元数据库连接到 ClickHouse报错解决 Docke…

轻松管理文件夹批量重命名:学会用关键词批量替换文件夹名称技巧

随着计算机中存储的文件和文件夹数量不断增加,如何有效地管理和组织它们变得尤为重要。批量重命名文件夹是提升文件管理效率的关键步骤之一。而利用云炫文件管理器中关键词批量替换文件夹名称的技巧,则可以帮助我们更快速地完成这一任务。 关键词批量替…

LeetCode例题讲解:876.链表的中间结点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 示例 1: 输入:head [1,2,3,4,5] 输出:[3,4,5] 解释:链表只有一个中间结点,值为 3 。…

KMeans,KNN,Mean-shift算法的学习

1.KMeans算法是什么? 在没有标准标签的情况下,以空间的k个节点为中心进行聚类,对最靠近他们的对象进行归类。 2.KMeans公式: 2. 1.关键分为三个部分: 1.一开始会定义n个中心点,然后计算各数据点与中心点…

浅谈云计算资源和服务

目录 前言 正文 专有名词及其首字母缩写 轻量级应用服务器 云服务器ECS 专有网络VPC 其他类服务 尾声 🔭 Hi,I’m Pleasure1234🌱 I’m currently learning Vue.js,SpringBoot,Computer Security and so on.👯 I’m studying in University o…

如何用Python创建目录以及自动创建缺失的父目录

在Python中,创建目录(也称为文件夹)是一个常见的任务,尤其是当你需要为文件系统上的某些文件创建存储位置时。幸运的是,Python的os模块提供了一个非常方便的函数os.makedirs(),它允许你创建一个目录&#x…

【AMBA Bus ACE 总线 8 -- ICache maintenance】

请阅读【AMBA Bus ACE 总线与Cache 专栏 】 欢迎学习:【嵌入式开发学习必备专栏】 文章目录 ACE ICache maintenanceACE ICache maintenance 图 1-1 当一个OS run 多个cpu的时候,根据调度算法的不同,OS 可以根据调度算法的不同分别 run 在某个具体的CPU上,因此,它们会有…

计算图与自动微分

计算图与自动微分 一、自动梯度计算1.1 数值微分(Numerical Differentiation)1.2 符号微分(Symbolic Differentiation)1.3 自动微分(Automatic Differentiation,AD)1.3.1 计算图1.3.2 正向传播1…

java技术总结

1.java基本数据类型? byte 1,short 2 ,int 4,long 8 ,float 4,double 8,boolean 1,char 2 2.java为什么要有包装类型? 前 6 个类派生于公共的超类 Number,而 Character 和 Boolean 是 Object 的直接子类。 被 final 修饰, Java 内置的包装类是无法被继承的。 包装…

FreeRTOS标准库例程代码

1.设备STM32F103C8T6 2.工程模板 单片机: 部分单片机的程序例程 - Gitee.comhttps://gitee.com/lovefoolnotme/singlechip/tree/master/STM32_FREERTOS/1.%E5%B7%A5%E7%A8%8B%E6%A8%A1%E6%9D%BF 3.代码 1-FreeRTOS移植模板 #include "system.h" #include "…

腾讯云coding代码托管平台配置问题公钥拉取失败提示 Permission denied(publickey)

前言 最近在学校有个课设多人开发一个游戏,要团队协作,选用了腾讯云的coding作为代码管理仓库,但在配置的时候遇到了一些问题,相比于github,发现腾讯的coding更难用,,,这里记录一下…

【进程替换】进程程序替换函数execl | 单进程程序替换原理

目录 直接看现象(单进程) 单进程程序替换原理 替换函数 直接看现象(单进程) 我们先使用execl来直接看现象man 3 execlexecute a file执行一个程序int execl(const char *path, const char *arg, ...);execl函数的返回值&#x…

使用GitLab自带的CI/CD功能在K8S集群里部署项目(四)

前置内容: 通过Docker Compose部署GitLab和GitLab Runner(一) 使用GitLab自带的CI/CD功能在本地部署项目(二) 使用GitLab自带的CI/CD功能在远程服务器部署项目(三) 一、K8S集群信息 节点名称…

Unity TileMap入门

概述 相信很多同学学习制作游戏都是从2D游戏开始制作的吧,瓦片地图相信大家都有接触,那接下来让我们学习一下这部分的内容吧! Tilemap AnimationFrameRate:设置每帧动画的播放速率。Color:瓦片地图的颜色TileAnchor:锚点,&#x…

笔试强训week4

day1 Q1 难度⭐⭐ 小易的升级之路_牛客题霸_牛客网 (nowcoder.com) 题目: 小易经常沉迷于网络游戏.有一次,他在玩一个打怪升级的游戏,他的角色的初始能力值为 a.在接下来的一段时间内,他将会依次遇见n个怪物,每个怪物的防御力为b1,b2,b3...bn. 如果遇到的怪物防…

马斯克:脑机接口迎来首例植入者,芯片接线发生故障。

马斯克旗下的脑机接口公司Neuralink近日传出关于首例植入者诺兰阿博脑机接口芯片故障的消息。根据Neuralink发布的文章,诺兰阿博的脑机设备发生了故障,多根植入他大脑的接线已经脱落,导致获取数据量减少。目前该公司正在研究导致接线脱落的原…

Java进阶08 集合(续)Stream流

Java进阶08 集合(续)&Stream流 一、HashSet集合类(续) 1、JDK7(-)HashSet原理解析 1.1 底层结构 数组链表 1.2 执行过程 ①创建一个默认长度为16的数组,数组名为table ②根据元素的哈希值跟数组的长度求余计…

灰狼优化算法(Grey Wolf Optimizer)

注意:本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 ([www.aideeplearning.cn]) 算法引言 灰狼算法(Grey Wolf Optimizer, GWO)是一种受自然界灰狼行为启发的优化算法。它模拟了灰狼的社会层次和狩猎策…

JS实现初始化、动态点击切换激活样式

食用须知&#xff0c;不懂得把代码交给AI解释一下&#xff0c;明白流程就会用了&#xff0c;本文只有js与html&#xff0c;样式代码一概没有&#xff1a; 效果展示 1、点击显示的盒子代码 <div data-v-e1dd37c4"" class"news-container main-width-contain…

JAVA获取application.yml配置文件的属性值

application.yml配置参数 方式一&#xff1a;使用Value方式(常用) 语法 Value("${配置文件中的key:默认值}") Value("${配置文件中的key}")方法1&#xff1a;使用的类文件中定义变量&#xff0c;直接使用变量 import org.springframework.beans.factory.an…
最新文章