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

ops/2024/9/20 7:25:36/ 标签: oceanbase, 分布式数据库, 并行执行, 性能优化
在诊断并行执行问题时,我们可以从两个主要方面展开分析。首先,从整体系统层面进行考量,比如检查网络是否畅通、磁盘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.ppmy.cn/ops/40819.html

相关文章

【软考网络工程师】每日练题学知识

1.在EIGRP协议中&#xff0c;某个路由器收到了两条路径到达目标网络&#xff0c;路径1的带宽为100Mbps&#xff0c;延迟2ms&#xff0c;路径2的带宽为50Mbps&#xff0c;迟为4ms&#xff0c;如果EIGRP使用带宽和延迟的综合度量标准&#xff0c;那么该路由器选择的最佳路径是&am…

超级好用的C++实用库之日志类

&#x1f4a1; 需要该C实用库源码的大佬们&#xff0c;可搜索微信公众号“希望睿智”。添加关注后&#xff0c;输入消息“超级好用的C实用库”&#xff0c;即可获得源码的下载链接。 概述 日志类主要用于在程序运行过程中记录信息、错误、警告以及其他需要跟踪的数据&#xff0…

【专利】一种日志快速分析方法、设备、存储介质

公开号CN116560938A申请号CN202310311478.5申请日2023.03.28 是我在超音速人工智能科技股份有限公司(833753) 职务作品&#xff0c;第一发明人是董事长夫妇&#xff0c;第二发明人是我。 ** 注意** &#xff1a; 内容比较多&#xff0c;还有流程图、界面等。请到 专利指定页面…

清华团队开发首个AI医院小镇模拟系统;阿里云发布通义千问 2.5:超越GPT-4能力;Mistral AI估值飙升至60亿美元

&#x1f989; AI新闻 &#x1f680; 清华团队开发首个AI医院小镇模拟系统 摘要&#xff1a;来自清华的研究团队最近开发出了一种创新的模拟系统&#xff0c;名为"Agent Hospital"&#xff0c;该系统能够完全模拟医患看病的全流程&#xff0c;其中包括分诊、挂号、…

VC 编程开发中的 封装类 :log日志类 和SQL server 操作类 源代码

VC 编程开发中的 封装类 &#xff1a;日志类 和SQL server 操作类 源代码 在VC&#xff08;Visual C&#xff09;开发中&#xff0c;日志文件输出是一个至关重要的环节&#xff0c;它对于程序调试、问题排查以及系统监控等方面都具有不可替代的作用。以下是对日志文件输出在VC开…

【PB案例学习笔记】-01创建应用、窗口与控件

写在前面 这是PB案例学习笔记系列文章的第一篇&#xff0c;也是最基础的一篇。后续文章中【创建程序基本框架】部分操作都跟这篇文章一样&#xff0c; 将不再重复。该系列文章是针对具有一定PB基础的读者&#xff0c;通过一个个由浅入深的编程实战案例学习&#xff0c;提高编…

Vue的学习 —— <vue指令>

目录 前言 正文 内容渲染指令 内容渲染指令的使用方法 v-text v-html 属性绑定指令 双向数据绑定指令 事件绑定指令 条件渲染指令 循环列表渲染指令 侦听器 前言 在完成Vue开发环境的搭建后&#xff0c;若想将Vue应用于实际项目&#xff0c;首要任务是学习Vue的基…

Java入门基础学习笔记14——数据类型转换

类型转换&#xff1a; 1、存在某种类型的变量赋值给另一种类型的变量&#xff1b; 2、存在不同类型的数据一起运算。 自动类型转换&#xff1a; 类型范围小的变量&#xff0c;可以直接赋值给类型范围大的变量。 byte类型赋值给int类型&#xff0c;就是自动类型转换。 pack…

Hugging Muti Agent:第一章

Hugging Muti Agent系列文章目录 学习资料链接&#xff1a;Hugging Muti Agent&#xff08;二月学习&#xff09; 文章目录 Hugging Muti Agent系列文章目录第一章&#xff1a;前期准备1.1 获取MetaGPT1.2 配置MetaGPT1.2.1 调用 ChatGPT API 服务 1.3 首次尝试 第一章&#…

爬虫工作量由小到大的思维转变---<第七十四章 > Scrapy爬虫关闭方法(close)的机制及其在爬虫优化中的重要性

前言 Scrapy爬虫也有一个至关重要的功能——close方法&#xff0c;它控制着爬虫的“生命周期”。本论文旨在探讨Scrapy框架中close方法的核心作用和定义&#xff0c;以及它在爬虫管理与优化过程中的重要性。我们将深入探索如何通过这个强大的功能去优雅地结束一个爬取任务&…

【Unity】Unity项目转抖音小游戏(二)云数据库和云函数

业务需求&#xff0c;开始接触一下抖音小游戏相关的内容&#xff0c;开发过程中记录一下流程。 抖音云官方文档&#xff1a;https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/cloud-function-debug 1.开通抖音云环境 抖音云地址&a…

【springboot】整合oauth2.0和security,使用图形验证码和邮箱验证码登录

思路 当使用OAuth和Security框架(如Spring Security)进行登录,并且不使用密码而使用验证码时,生成Token的过程通常涉及以下几个步骤: 1.验证码生成与验证: 首先,系统会生成一个图形验证码并将其展示给用户。 用户输入他们看到的验证码。 系统验证用户输入的验证码是否…

docker的使用

docker的使用 1.首先&#xff0c;拉取一个镜像&#xff0c;如 docker pull 镜像名称 # 官方镜像 docker image pull 镜像名称 # 或简写为 docker pull 镜像名称 # 比如 docker pull ubuntu docker pull ubuntu:16.04# 个人镜像 docker pull 仓库名称/镜像名称 docker pull …

Linux sndconfig命令教程:如何在Linux下设置声卡(附实例详解和注意事项)

Linux sndconfig命令介绍 sndconfig&#xff08;Sound Configuration&#xff09;是一个用于设置声卡的命令。它支持即插即用&#xff08;Plug and Play&#xff0c;PnP&#xff09;设置&#xff0c;可以自动检测并设置PnP声卡。sndconfig命令可以帮助用户在Linux系统中配置声…

如何提高自己的全局视野?

以下是一些可以帮助提高全局视野的方法&#xff1a; 1. 广泛学习不同领域知识&#xff1a;包括但不限于技术相关的各个领域、业务知识、行业动态等&#xff0c;拓宽知识面。 2. 参与大型项目&#xff1a;积极投身到复杂的、规模较大的项目中&#xff0c;在实践中感受和理解系…

计算机毕业设计hadoop+spark+hive知识图谱bilibili视频数据分析可视化大屏 视频推荐系统 预测系统 实时计算 离线计算 数据仓库

研究意义 随着互联网的快速发展&#xff0c;人们面临着海量的视频内容&#xff0c;如何从这些繁杂的视频中找到自己感兴趣的内容成为一个重要的问题[1]。推荐系统作为一种解决信息过载问题的重要工具&#xff0c;能够根据用户的历史行为和偏好&#xff0c;预测用户可能感兴趣的…

nginx 负载均衡配置详解

基于 ${nginx_home}/conf/nginx.conf 文件配置实现&#xff0c;如下&#xff1a; http {# 定义server地址upstream server_group {server 192.168.xxx.1:8080;server 192.168.xxx.2:8080;server 192.168.xxx.3:8080;}server {listen 80;location / {root html;index …

Spring框架概述

目录 1. Spring框架的起源 2. Spring框架的构成 3. Spring的发展历程 4. Spring的开发环境 4.1. Maven安装与配置 &#xff08;1&#xff09;Maven的下载与安装 &#xff08;2&#xff09;配置Maven的环境变量 &#xff08;3&#xff09;本地仓库的配置 &#xff08;4…

变频器通过Modbus转Profinet网关接电机与PLC通讯在自动化的应用

Modbus转Profinet网关&#xff08;XD-MDPN100/300/600&#xff09;的作用是将Modbus协议转换为Profinet协议&#xff0c;支持Modbus RTU主站/从站&#xff0c;并且Modbus转Profinet网关设备自带网口和串口&#xff0c;既可以实现协议转换的同时&#xff0c;也可以实现接口的转换…

通过EXCEL控制PLC启停电机的一种方法

概述 本例将介绍用微软EXCEL电子表格控制西门子S7-1200 PLC实现电机启停的一种方法。 第1步&#xff1a; 添加PLC设备&#xff0c;选择西门子S7-1214C CPU&#xff0c;设置IP地址&#xff1a;192.168.18.18&#xff0c;子网掩码&#xff1a;255.255.255.0。 第2步&#xff1a…