如何进行并行执行的诊断与调优 —— 《OceanBase 并行执行》系列 6

在诊断并行执行问题时,我们可以从两个主要方面展开分析。首先,从整体系统层面进行考量,比如检查网络是否畅通、磁盘IO是否过载、CPU资源是否已用满;其次,针对具体的SQL语句进行深入剖析,定位问题SQL,并探究其内部状态。

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

并行执行概念
如何手动设置并行度
并行执行线程资源管理方式
并行执行的4种类别
并行执行参数的应用技巧

6.1 系统诊断

在业务比较繁忙的系统重出现性能问题时,首先需要在系统层面做初步诊断。一般有两种途径:

  • OCP(OceanBase Cloud Platform),支持可视化观测系统性能
  • tsar 等命令行系统工具,支持查询网络、磁盘、CPU等的历史监控数据

tsar 是一个系统监控和性能分析工具,它可以提供关于 CPU、磁盘、网络等方面的详细信息。以下是 tsar 命令的几个常见用法:

tsar --cpu
tsar --io
tsar --traffic

除了以上示例外,tsar 还支持其他选项和参数,例如通过参数-d 2 可以查出两天前到现在的数据,-i 1 表示以每次1分钟作为采集显示。

tsar -n 2 -i 1 --cpu

如果出现磁盘或网络打爆,则优先从硬件容量过小或并发压力过大角度解决问题。

6.2 SQL 诊断

当遇到并行执行问题时,可以从 SQL 层面、并行执行线程层面、算子层面逐层检查。

6.2.1 确认 SQL 还在执行

确认 SQL 在正常执行:关注 TIME 字段,每次查询 GV$OB_PROCESSLIST 视图 TIME 字段都在增长,并且 STATE 为 ACTIVE,说明 Query 还在执行。

确认 SQL 是否在反复重试:如果 SQL 是因为反复重试导致没有返回结果,RETRY_CNT、RETRY_INFO 字段会有相关信息。其中 RETRY_CNT 是表示重试了多少次了,RETRY_INFO 是最后一次重试的原因。没有重试发生的时候,RETRY_CNT 为 0。TOTAL_TIME 字段表示包含每次重试在内的累计执行时间。如果发现 SQL 在反复重试,则根据 RETRY_INFO 中给出的错误码判断是否需要干预。OBServer v4.1 之前,最常见的一个错误是 -4138(OB_SNAPSHOT_DISCARDED),遇到这种情况,按照本文中 《4 并行执行分类》中的 4.2.4 节指示,调大 undo_retention 值即可解决。对于其它错误,如 -4038(OB_NOT_MASTER)等,无需任何处理,一般可以自动重试成功。如果重试次数总是大于1,并且确认系统整体状态平稳,可以联系 OceanBase 研发做进一步判断。

-- MySQL 模式
SELECTTENANT,INFO,TRACE_ID,STATE,TIME,TOTAL_TIME,RETRY_CNT,RETRY_INFO
FROMoceanbase.GV$OB_PROCESSLIST;

如果发现 GV$OB_PROCESSLIST 里还有对应的 SQL,但状态被标记为 SESSION_KILLED,并且一直没有退出,那么需要联系 OceanBase 研发,报告 bug。这可能是因为:

  • 有逻辑没有正确检测 SESSION KILLED 状态,未能及时退出执行流程

6.2.2 确认 SQL 还在执行并行查询

OBServer 集群中,所有活跃的并行执行线程都可以通过 GV$OB_PX_WORKER_STAT视图查看到。

-- MySQL 模式
OceanBase(admin@oceanbase)>select * from oceanbase.GV$OB_PX_WORKER_STAT;
SESSION_ID: 3221520411TENANT_ID: 1002SVR_IP: 192.168.0.1SVR_PORT: 19510TRACE_ID: Y4C360B9E1F4D-0005F9A76E9E66B2-0-0QC_ID: 1SQC_ID: 0WORKER_ID: 0DFO_ID: 0
START_TIME: 2023-04-23 17:29:17.372461-- Oracle 模式
OceanBase(root@SYS)>select * from SYS.GV$OB_PX_WORKER_STAT;
SESSION_ID: 3221520410TENANT_ID: 1004SVR_IP: 192.168.0.1SVR_PORT: 19510TRACE_ID: Y4C360B9E1F4D-0005F9A76E9E66B1-0-0QC_ID: 1SQC_ID: 0WORKER_ID: 0DFO_ID: 0
START_TIME: 2023-04-23 17:29:15.372461

结合从 GV$OB_PROCESSLIST 拿到的 TRACE_ID,通过这个视图可以看到 SQL 当前正在执行哪些 DFO,执行了多久等信息。

如果这个视图里什么也查不到,但 GV$OB_PROCESSLIST 里依然可以看到相应 SQL,可能的原因包括:

  • 所有 DFO 均已执行完成,结果集较大,当前正处在向客户端吐数据阶段
  • 除了最顶层 DFO 外,其余所有 DFO 均已执行完成

6.2.3 确认每个算子的执行状况

通过 oceanbase.GV$SQL_PLAN_MONITOR (MySQL) 或 SYS.GV$SQL_PLAN_MONITOR(Oracle)可以查看每个并行工作线程中每个算子的执行状态。从 OBServer v4.1 起,GV$SQL_PLAN_MONITOR包含两部分数据:

  • 已经执行完成的算子。所谓执行完成是指这个算子已经调用过 close 接口,在当前线程中不再处理任何数据。
  • 正在执行的算子。所谓正在执行是指这个算子还没有调用 close 接口,正在处理数据过程中。读取这部分算子的数据,需要在查询 GV$SQL_PLAN_MONITOR 视图的 where 条件中指定 request_id < 0。在使用 request_id < 0 条件查询本视图时,我们也称为访问 “Realtime SQL PLAN MONITOR”。本访问接口未来可能会变化。

OBServer 4.1 之前,仅支持查看已经执行完成的算子状态。

GV$SQL_PLAN_MONITOR中有几个重要的域:

  • TRACE_ID:它唯一标识了一条 SQL
  • PLAN_LINE_ID:算子在执行计划中的编号,对应于通过 explain 语句查看到的编号
  • PLAN_OPERATION:算子名称,如 TABLE SCAN、HASH JOIN
  • OUTPUT_ROWS:当前算子已经输出的行数
  • FIRST_CHANGE_TIME:算子吐出首行数据时间
  • LAST_CHANGE_TIME:算子吐出最后一行数据时间
  • FIRST_REFRESH_TIME:算子开始监控时间
  • LAST_REFRESH_TIME:算子结束监控时间

根据上面几个域,基本就能刻画出一个算子处理数据的主要动作了。举例几个场景:

  1. 查看一个已经执行完成的 SQL,每个算子使用了多少个线程来执行:
SELECT PLAN_LINE_ID, PLAN_OPERATION, COUNT(*) THREADS
FROM GV$SQL_PLAN_MONITOR
WHERE TRACE_ID = 'YA1E824573385-00053C8A6AB28111-0-0'
GROUP BY PLAN_LINE_ID, PLAN_OPERATION
ORDER BY PLAN_LINE_ID;+--------------+------------------------+---------+
| PLAN_LINE_ID | PLAN_OPERATION         | THREADS |
+--------------+------------------------+---------+
|            0 | PHY_PX_FIFO_COORD      |       1 |
|            1 | PHY_PX_REDUCE_TRANSMIT |       2 |
|            2 | PHY_GRANULE_ITERATOR   |       2 |
|            3 | PHY_TABLE_SCAN         |       2 |
+--------------+------------------------+---------+
4 rows in set (0.104 sec)
  1. 查看正在执行的 SQL,当前正在执行哪些算子,使用了多少线程,已经吐出了多少行:
SELECT PLAN_LINE_ID, CONCAT(LPAD('', PLAN_DEPTH, ' '), PLAN_OPERATION) OPERATOR, COUNT(*) THREADS, SUM(OUTPUT_ROWS) ROWS
FROM GV$SQL_PLAN_MONITOR
WHERE TRACE_ID = 'YA1E824573385-00053C8A6AB28111-0-0' AND REQUEST_ID < 0
GROUP BY PLAN_LINE_ID, PLAN_OPERATION, PLAN_DEPTH
ORDER BY PLAN_LINE_ID;
  1. 查看一个已经执行完成的 SQL,每个算子处理了多少行数据,吐出了多少行数据:
SELECT PLAN_LINE_ID, CONCAT(LPAD('', PLAN_DEPTH, ' '), PLAN_OPERATION) OPERATOR, SUM(OUTPUT_ROWS) ROWS
FROM GV$SQL_PLAN_MONITOR
WHERE TRACE_ID = 'Y4C360B9E1F4D-0005F9A76E9E6193-0-0'
GROUP BY PLAN_LINE_ID, PLAN_OPERATION, PLAN_DEPTH
ORDER BY PLAN_LINE_ID;
+--------------+-----------------------------------+------+
| PLAN_LINE_ID | OPERATOR                          | ROWS |
+--------------+-----------------------------------+------+
|            0 | PHY_PX_MERGE_SORT_COORD           |    2 |
|            1 |  PHY_PX_REDUCE_TRANSMIT           |    2 |
|            2 |   PHY_SORT                        |    2 |
|            3 |    PHY_HASH_GROUP_BY              |    2 |
|            4 |     PHY_PX_FIFO_RECEIVE           |    2 |
|            5 |      PHY_PX_DIST_TRANSMIT         |    2 |
|            6 |       PHY_HASH_GROUP_BY           |    2 |
|            7 |        PHY_HASH_JOIN              | 2002 |
|            8 |         PHY_HASH_JOIN             | 2002 |
|            9 |          PHY_JOIN_FILTER          | 8192 |
|           10 |           PHY_PX_FIFO_RECEIVE     | 8192 |
|           11 |            PHY_PX_REPART_TRANSMIT | 8192 |
|           12 |             PHY_GRANULE_ITERATOR  | 8192 |
|           13 |              PHY_TABLE_SCAN       | 8192 |
|           14 |          PHY_GRANULE_ITERATOR     | 8192 |
|           15 |           PHY_TABLE_SCAN          | 8192 |
|           16 |         PHY_GRANULE_ITERATOR      | 8192 |
|           17 |          PHY_TABLE_SCAN           | 8192 |
+--------------+-----------------------------------+------+
18 rows in set (0.107 sec)

为了展示美观,上面使用了一个域 PLAN_DEPTH来做缩进处理,PLAN_DEPTH 表示这个算子在算子树中的深度。

注:

  1. 尚未调度的 DFO 的算子信息,不会出现在 GV$SQL_PLAN_MONITOR 中。
  2. 在一个 PL 中如果包含多条 SQL,它们的 TRACE_ID 相同

6.3 并行执行调优技巧

本章介绍一些基础的 OceanBase 并行执行调优技巧。调优是一个永无止境的话题,本章内容也会与时俱进,不断更新。

6.3.1 手动收集统计信息 

如果优化器中保存的统计信息陈旧,可能导致生成的计划不优。OBServer v3.2 和 OBServer v4.1 分别提供了手动收集统计信息的接口:OceanBase 优化器统计信息 (4.x 版本)

OBServer v4.1 手动收集主表、索引表的语法如下:

-- 收集用户TEST的表T1的全局级别的统计信息,所有列的桶个数设定为auto策略:
call dbms_stats.gather_table_stats('TEST', 'T1', granularity=>'GLOBAL', method_opt=>'FOR ALL COLUMNS SIZE AUTO');
-- 收集用户TEST下表T1的索引IDX的索引统计信息,并行度4(IDX不唯一,需指定表名称)
call dbms_stats.gather_index_stats('TEST', 'IDX', degree=>4, tabname=>'T1');

6.3.2 修改分区方式使用 Partition Wise Join

PoC 场景中,如果有大表 JOIN,并且在业务允许的前提下,可以让大表使用相同的分区方式,并且将他们绑定到同一个表组上,这样可以实现性能最佳的 partition wise join。使用 partition wise join 时,并行度也要调整得和分区数相适应,这样可以获得最佳性能。

6.3.3 并行度与分区数适配

一般来说,并行度与分区数符合一定的整比例关系,能得到较好的性能。详细论述参考之前发布的一篇博客《并行执行学习笔记 1 —— 并行执行概念》中的《1.6 通过均衡负载来优化性能》一节。

6.3.4 创建索引

创建合适的索引,能减少数据的扫描量,可以提高并行执行性能。在哪些表、哪些列上建索引,没有一个通用的方案,需要基于具体 SQL 具体分析。创建索引的基础技巧可以参考之前发布的一篇博客《SQL 性能调优学习笔记 1 —— 索引调优》。

6.3.5 创建复制表

OBServer v4.2 及之后版本,通过创建复制表,能减少数据重分布,可以提高并行执行性能,详见 OceanBase 官方文档中创建表的《创建复制表》章节。基本语法举例如下:

create table dup_t1(c1 int) duplicate_scope = 'cluster';

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML炫酷的相册

目录 写在前面 HTML简介 完整代码 代码分析 系列推荐 写在最后 写在前面 本期小编给大家带来一个炫酷的旋转相册&#xff0c;快来解锁属于你的独家记忆吧&#xff01; HTML简介 HTML&#xff08;全称为超文本标记语言&#xff09;是一种用于创建网页结构和内容的标记语…

前端笔记-day06

文章目录 01-浮动-基本使用02-浮动-产品布局03-浮动-清除浮动带来的影响04-清除浮动-额外标签法05-清除浮动-单伪元素法06-清除浮动-双伪元素法单伪元素和双伪元素CSS 07-清除浮动-overflow08-flex布局-体验09-flex布局-组成10-flex布局-主轴对齐方式11-flex布局-侧轴对齐方式1…

vuex核心概念-getters

除了state之外&#xff0c;有时我们还需要从state中派生出一些状态&#xff0c;这些状态是依赖state的&#xff0c;此时会用到getters。

景源畅信:小白如何做抖音电商怎么样?

在数字浪潮中崛起的抖音电商&#xff0c;以其独特的平台优势吸引了众多创业者的目光。特别是对于初入电商领域的“小白”来说&#xff0c;如何在这个全新的领域站稳脚跟&#xff0c;成为他们迫切需要解答的问题。接下来&#xff0c;我们将深入探讨小白如何在抖音电商中开辟属于…

课时124:awk实践_进阶知识_逻辑运算

1.2.3 逻辑运算 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习 基础知识 简介 所谓的逻辑运算&#xff0c;其实指的就是 与或非的操作。基本语法格式如下&#xff1a;与&& - 并且关系或|| - 或者关系非&#xff01; - 取反关系简单实…

蓝桥杯备战18.[蓝桥杯 2021 省 AB] 砝码称重

P8742 [蓝桥杯 2021 省 AB] 砝码称重 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using namespace std; #define endl \n #define int long long const int N 2e510; int a[N],w[N]; signed main() {std::ios::sync_with_stdio(0),cin.tie(0…

Golang的select底层数据结构与特性

select关键字用于处理同时来自多个通道的数据。它的基本工作原理是“随机选择”满足条件的分支去执行。如果没有分支满足条件(即所有通道都无法读/写)&#xff0c;select会阻塞&#xff0c;直到有分支满足条件。如果select包含default分支&#xff0c;当其他分支都不满足条件时…

使用 Python 中的 TensorFlow 检测垃圾短信

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

Python实现对线程的监控及异常时强制杀死线程的技术方案探讨

在Python中&#xff0c;使用threading库创建的线程并没有提供一个直接的方式来“杀死”或强制停止一个线程。这是因为强制终止线程可能会导致程序状态不一致、数据损坏或资源未正确释放等问题。Python设计者选择不在threading模块中提供这样的功能&#xff0c;以鼓励更安全的编…

UIKit常用API:Transform

需求 使用Transform系列的API&#xff0c;该API中提供了旋转、平移等功能。其中函数中带make的效果是只变化一次&#xff0c;不带make可变化多次。此外&#xff0c;还有恢复函数&#xff1a;CGAffineTransformIdentity。 代码实现 注意按钮绑定的是同一个响应事件&#xff0…

漏洞修复:TLS Client-initiated重协商攻击(CVE-2011-1473)

目录 一、漏洞描述 二、漏洞验证 三、实现方式 四、解决方法 1.通过代码添加 2.通过启动参数添加 五、openssl s_client命令 一、漏洞描述 服务器支持 TLS Client-initiated 重协商攻击(CVE-2011-1473)【原理扫描】 使用绿盟等漏洞扫描工具扫描https端口的服务时可能会…

使用Halcon进行图像预处理的策略

图像预处理是机器视觉系统中的一个关键步骤&#xff0c;它有助于提高图像质量&#xff0c;从而使得后续的图像分析和特征提取更加准确。在 Halcon 中&#xff0c;图像预处理通常包括滤波、对比度增强、归一化、边缘增强等操作。以下是一些使用 Halcon 进行图像预处理的策略&…

【React】React的懒加载组件lazy和Suspense

在一个多路由项目中&#xff0c;页面加载时&#xff0c;所有的路由组件都会被加载 如果我们有很多个路由组件&#xff0c;但是用户只点击了几个&#xff0c;这就会有很大的消耗&#xff0c;因此我们需要做懒加载处理&#xff0c;我们点击哪个时&#xff0c;才去加载哪一个 而Re…

2.数据类型与变量(java篇)

目录 数据类型与变量 数据类型 变量 整型变量 长整型变量 短整型变量 字节型变量 浮点型变量 双精度浮点型 单精度浮点型 字符型变量 布尔型变量&#xff08;boolean&#xff09; 类型转换 自动类型转换(隐式) 强制类型转换(显式) 类型提升 字符串类型 数据类…

go使用nacos作为配置中心时遇到的一个错误

docker安装nacos如下&#xff08;有坑&#xff09;&#xff1a; 一文教你使用 Docker 启动并安装 Nacos-阿里云开发者社区 报错如下&#xff1a; read config from both server and cache fail, errread cache file Config Encrypted Data Key failed. cause file doesnt ex…

百亿补贴为什么用 H5?H5 未来会如何发展?

百亿补贴为什么用 H5&#xff1f;H5 未来会如何发展&#xff1f; 本人有一些分析预测。当然&#xff0c;这些分析预测只是个人观点&#xff0c;如果你有不同的意见&#xff0c;欢迎在评论区讨论交流。 百亿补贴为什么用 H5 我们先看两张图&#xff0c;在 Android 手机开发者…

java设计模式 建造者设计模式

建造者模式&#xff08;Builder Pattern&#xff09;是一种设计模式&#xff0c;用于将复杂对象的构建与其表示分离&#xff0c;以便同样的构建过程可以创建不同的表示。以下是建造者模式的一个案例分析&#xff0c;以及在Java中的实现。 ### 案例分析 假设我们要设计一个用于…

单元测试与集成测试:软件质量的双重保障

目录 概述 单元测试 集成测试 单元测试的方法 白盒测试 黑盒测试 白盒测试的方法和用例设计 代码审查 集成测试 单元测试工具 结语 在软件开发中&#xff0c;测试是一个不可或缺的环节&#xff0c;它能够帮助我们发现和修复缺陷&#xff0c;确保软件的质量和可靠性。…

基于UDP的网络客户端和服务端模型IO函数

服务器端 udp_server.c #include <stdio.h> // 引入标准输入输出库 #include <sys/types.h> // 引入基本系统数据类型 #include <sys/socket.h> // 引入socket编程相关的库 #include <netinet/in.h> // 引入网络…

2024年3月 青少年等级考试机器人理论真题二级

202403 青少年等级考试机器人理论真题二级 第 1 题 一个机器小车&#xff0c;用左右两个电机分别控制左右车轮&#xff0c;左侧电机转速是100rpm&#xff0c;右侧电机转速是50rpm&#xff0c;则此机器小车&#xff1f;&#xff08; &#xff09; A&#xff1a;原地右转 B&am…