ODC 如何精确呈现SQL耗时 | OceanBase 开发者工具解析

前言

在程序员或DBA的日常工作中,编写并执行SQL语句如同日常饮食中的一餐一饭,再寻常不过。然而,在使用命令行或黑屏客户端处理SQL时,常会遇到编写难、错误排查缓慢以及查询结果可读性不佳等难题,因此,图形化工具成为了我们调试与执行SQL的首选。那么,你是否曾好奇,当我们借助直观易用的开发者工具执行一条SQL语句时,从按下执行按钮的那一刻起,直至结果呈现、查询执行计划展现的过程,这条SQL语句究竟经历了怎样的旅程?倘若执行响应迟缓,又是哪个环节遭遇了瓶颈呢?

ODC 作为OceanBase的数据库开发者工具,致力于为用户提供更高效、更易用的 SQL 执行与诊断方案,在 4.1.0 版本,对 SQL 执行阶段的耗时也做了进一步的细化展示,以方便用户更清晰的了解 SQL 耗时详情。本文以 OceanBase Oracle 模式下一条 SQL 在 ODC 以及 OBServer 上的生命周期为例,介绍 ODC SQL 执行过程及耗时计算方案。

1 SQL 的执行过程

前置处理

在 SQL 被实际执行前,首先会被解析,获取其操作对象类型、是否加写锁(for update)、是否为多表查询等基础信息。之后根据解析结果,若其满足一定的条件,可能会对 SQL 进行改写操作。

Apply SQL

改写包括两点,一是为了提升查询性能,当语句为 SELECT 类型,查询字段中包含 * 且非 .* 的语句时,会尝试替换为 table.* ;二是会在 SELECT 后增加 ROWID AS __ODC_INTERNAL_ROWID__ 的字段,这是因为结果集编辑时,若查询中未指定 ROWID 字段,那么可能会出现数据误更新的情况。

SELECT * FROM DEMO;为例,在发出执行请求后,会被改写为:

SELECT ROWID AS "__ODC_INTERNAL_ROWID__", DEMO.* FROM DEMO;

Validate SQL semantics

尽管对是否改写 SQL 已经经过了一定的判定,但仍然可能出现改写后无法执行的情况,例如查询 GV$SYSSTAT 等不支持 ROWID 的系统视图,那么即便语法不存在错误,也会导致执行失败。

为了避免改写导致的执行失败,在真实执行 SQL 之前,会执行 EXPLAIN + SQL ,若执行成功则说明改写成功,执行改写后的 SQL 并返回结果,否则仍然会采用原 SQL。

SQL 执行

SQL 执行阶段是 SQL 生命周期中最主要的阶段,其经过内部处理和准备后,通过网络协议一次或多次发送至 OceanBase Server 端,由 OBServer 进行具体执行操作,之后将结果以同样的方式返回客户端。

一条 SQL 在调用 JDBC 驱动执行语句后,驱动首先会进行一系列准备,例如设置查询行数限制、判断是否通过代理连接 Server 、设置执行超时计时器 等,这个阶段记作 Jdbc prepare 。

SQL 在从客户端发送至 OceanBase Server 端后,会进入等待队列,若租户 CPU 不足或服务器负载过高,则此过程可能会耗费大量时间。结束排队后,将会对其进行解析、改写和获取 SELECT 语句的执行计划,该过程若未命中缓存,也可能占用较长时间。拿到物理执行计划后,执行器才会调用线程执行该条 SQL ,并将计划保存至缓存中。为简化理解成本,上述一系列操作合并记作 OBServer wait 阶段。

OBServer 执行完成后,将数据返回客户端,通过 Get result-set 阶段,从返回结果中解析出要展示的数据,至此,便是一条 SQL 的实际执行过程。

后置处理

在获取到执行结果后,为了客户端的展示、编辑及错误提示,还会对该条 SQL 和执行结果进行几项后置处理。

Init SQL type

针对不同类型的 SQL,Navicat、SQL Developer 等数据库开发工具一般会给出不同的结果展示方式,例如 Navicat 对于 DML(INSERT、DELETE、UPDATE)类型语句会展示 Affected rows 影响行数,而对于 DDL、DQL 等仅提示 OK 执行成功,且展示 DQL 类型的查询结果。

ODC 对 SQL 类型的结果展示逻辑与 Navicat 基本相同,而解析类型的过程即被记作 Init SQL type 阶段,具体解析工作通过 OceanBase sql-parser 工具完成。

Init column comment 与 Init editable Info

在解析完 SQL 类型后,如果执行结果包含一个或多个表的列数据,则 ODC 会从字典视图 ALL_TAB_COLUMNS 中尝试获取相关列和表信息,并将其暂存在缓存中,以供接下来获取列注释和判断结果集是否可编辑。

若当前 SQL 涉及到对表或视图对象的查询,那么在展示时会显示列注释。而且,若当前 SQL 为单表查询,那么 ODC 能够允许用户对结果集进行编辑;若为多表查询,有且只有其中一张表的 ROWID 被指定,则指定 ROWID 的表的列可编辑,其余列不可。

Init warning message

OceanBase 数据库提供了字典视图 ALL_ERRORS,用于查看当前用户可访问的存储对象的错误。由于 SQL 窗口同样可以执行 PL,因此在执行结束后,ODC 将尝试查询 ALL_ERRORS 视图,通过对象名名称、Schema 名称和对象类型进行标识。若存在错误信息,则将其结构化处理后返回给用户。

至此,SQL 和结果集的后置处理也结束了,我们通过在 执行记录 界面中的 DB 耗时,查看上述各阶段的具体耗时。

2 OBServer 上的执行时间

SQL_AUDIT 视图

OceanBase 数据库将每一次 SQL 执行的来源、执行状态、详细耗时等信息存储在 GV$SQL_AUDIT 系统视图中,您可以通过该视图来查询 SQL 在 OBServer 端的耗时详情。

SQL_AUDIT 视图相关字段如下所示:

字段名称类型描述
TRACE_IDVARCHAR2(128)该语句的 trace_id
TENANT_IDNUMBER(38)发送请求的租户 ID
REQUEST_TIMENUMBER(38)开始执行时间点,单位:微秒
ELAPSED_TIMENUMBER(38)接收到请求到执行结束所消耗的总时间
EXECUTE_TIMENUMBER(38)实际计划执行所消耗的时间

注:在 OceanBase 4.0 版本之后,GV$SQL_AUDIT 命名更改为 GV$OB_SQL_AUDIT 。该视图按照租户拆分,除了系统租户,其他租户不能跨租户查询。

SQL TRACE

此外, OceanBase 支持 Trace 功能,通过变量 OB_ENABLE_TRACE_LOG 控制。

开启该功能后,可以使用SHOW TRACE命令来快速获取最近一次 SQL 请求的完整日志。该命令获取的数据格式如下所示:

示例结果说明如下:

  • Title 列包含整个 SQL 执行经历的各个阶段的信息以及该 SQL 真实的执行路径。若结果中有经过 Resolve、Transform、Optimizer 和 Code Generate 四个流程,则说明该 SQL 重新生成了计划,没有命中 Plan Cache。
  • KeyValue 列包含一些执行信息,可以用于排查问题:
    • TRACE_ID 可以作为 SQL_AUDIT 视图中的过滤条件,快速找到该 SQL 执行信息,同时也可以通过该 TRACE_ID 快速查找相关的 OBServer 日志。
    • plan_id 可以用于在 v$plan_cache_plan_explain 中查看 Plan Cache 中缓存的具体执行计划。
    • phy_plan_type 指出该次执行计划的类型(1 表示本地计划/2 表示远程计划/3 表示分布式计划),可以辅助 SQL 诊断。
  • Time 列显示上一个阶段点到这次阶段点执行耗时。如果某个 SQL 执行很慢,则通过查看 TIME 列,能够快速定位出具体是哪个阶段执行较慢,然后再进行具体分析。假设执行耗时主要在生成计划过程中,则只需要分析没有命中 Plan Cache 的原因,可能是计划淘汰后第一次执行该 SQL,或是 Plan Cache 不支持的 SQL。

3 ODC 如何计算耗时

Jdbc 准备耗时

JDBC驱动记录了执行请求发送和接收结果的时间节点,通过api来获取 JDBC 网络开销的时间,ODC 通过调用接口获取两个关键时间戳,将其作为计算耗时的数据来源。

Jdbc prepare 阶段耗时通过计算真实发送网络请求调用执行方法之间的时间差得到。当 Server 端的查询结果较多时,会分多次网络通信返回数据,我们使用 Jdbc 记录第一个数据包接收的时间戳,用于后续计算 Network consumption 阶段的耗时。

实际执行耗时

在 SQL 执行完成后,ODC 会通过 SHOW TRACE 命令获取查询该条 SQL 在 OBServer 端的实际执行日志。通过分析计算该日志,可得到该次请求的 ELAPSED_TIME (接收到请求到执行结束消耗的总时间)和 EXECUTE_TIME (实际执行物理计划所消耗的时间)。

其中 EXECUTE_TIME 即为 OBServer Execute SQL 阶段耗时,且被展示为执行记录中做外层的 DB 耗时。解析、改写、获取执行计划等预处理操作的耗时为除 EXECUTE_TIME 之外时间之和,合并记作 OBServer wait 阶段。

网络耗时

虽然 GV$SQL_AUDIT 视图中记录了每条 SQL 执行请求的 REQUEST_TIME ,理论上可通过该时间戳与请求发送之间的时间差获取到网络延时。但实际上由于该字段取自 OBServer 本地服务器时钟,而不同服务器间的·,时钟存在时间差异,因此难以单独计算请求发送或接收的耗时。

ODC 将接收到第一个回包的时间节点与请求发送的时间节点之间的差值作为请求往返时间,并减去上一步获取到的 ELAPSED_TIME 即 OBServer 端总耗时,从而获取到请求发送与接收的总网络耗时,记作 Network consumption 阶段。

4 ODC 执行耗时展示

在 ODC 中,我们可以通过“执行记录”界面的 “DB 耗时”功能查看 SQL 执行各个阶段的耗时,进而定位问题所在。ODC 在 4.1.0 版本,将每个阶段的执行耗时时间单位进行了自适应处理,保留小数点后两位,且对 SQL 执行阶段的耗时也做了进一步的细化展示,以方便用户更清晰的了解 SQL 耗时详情。

文中的例子是在 OB-Oracle 模式下运行,OB-MySQL 模式与之相比,不会对 SQL 进行解析与改写,而是直接交由驱动和 OBServer 执行,其余阶段基本相同,因此不再赘述。

总结

SQL 的一生很长,本文仅仅是简要描述了其被 ODC 执行时,各个生命周期中的主要工作以及耗时是如何得到的,对 SQL 在 OceanBase Server 端内部的执行过程也仅是粗略介绍。

后续的文章中将会带大家了解 ODC 的权限管理模型,敬请期待

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

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

相关文章

Bugku CTF_Web——No one knows regex better than me

Bugku CTF_Web——No one knows regex better than me 进入靶场 一段PHP代码 <?php error_reporting(0); $zero$_REQUEST[zero]; $first$_REQUEST[first]; $second$zero.$first; if(preg_match_all("/Yeedo|wants|a|girl|friend|or|a|flag/i",$second)){$key$…

爬虫——JSON数据处理

第三节&#xff1a;JSON数据处理 在爬虫开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;是最常见的数据格式之一&#xff0c;特别是在从API或动态网页中抓取数据时。JSON格式因其结构简单、可读性强、易于与其他系统交互而广泛应用于前端与后端的数…

OpenHarmony-1.启动流程

OpenHarmony启动流程 1.OpenHarmony 标准系统启动引导流程 OpenHarmony标准系统默认支持以下几个镜像&#xff1a; 每个开发板都需要在存储器上划分好分区来存放上述镜像&#xff0c;SOC启动时都由bootloader来加载这些镜像&#xff0c;具体过程包括以下几个大的步骤&#xf…

力扣刷题日记之150.逆波兰表达式求值

今天继续给大家分享一道力扣的做题心得今天这道题目是 150.逆波兰表达式求值 题目如下&#xff0c;题目链接&#xff1a;https://leetcode.cn/problems/evaluate-reverse-polish-notation 1&#xff0c;题目分析 这道题说是一道中等难度的题目&#xff0c;其实如果理解了其中的…

Redis五大基本类型——String字符串命令详解(命令用法详解+思维导图详解)

目录 一、String字符串类型介绍 二、常见命令 1、SET 2、GET 3、MGET 4、MSET 使用MGET 和 使用多次GET的区别 5、DEL 6、SETNX SET、SET NX和SET XX执行流程 7、INCR 8、INCRBY 9、DECR 10、DECYBY 11、INCRBYFLOAT 12、APPEND 13、GETRANGE 14、SETRANGE …

如何知道表之间的关系(为了知识图谱的构建)

今天就简单点&#xff0c;把今天花时间做的一个程序说下。 我们在做常规知识图谱的时候&#xff0c;面临一个问题就是要知道关系是如何建立。如果表的数量比较少&#xff0c;人工来做还是比较容易的。 如果有非常多的表&#xff0c;并且这些表之间的关联关系都不清楚的情况下…

【软件测试】一个简单的自动化Java程序编写

文章目录 自动化自动化概念回归测试常见面试题 自动化测试金字塔 Web 自动化测试驱动 Selenium一个简单的自动化示例安装 selenium 库使⽤selenium编写代码 自动化 自动化概念 自动的代替人的行为完成操作。自动化在生活中处处可见 生活中的自动化可以减少人力的消耗&#x…

网络学习第四篇

引言&#xff1a; 我们在第三篇的时候出现了错误&#xff0c;我们要就行排错&#xff0c;那么我们要知道一下怎么配置静态路由实现ping通&#xff0c;这样子我们才知道下一跳到底是什么&#xff0c;为什么这样子做。 实验目的 理解和掌握静态路由的基本概念和配置方法。 实…

LeetCode题解:17.电话号码的数字组合【Python题解超详细,回溯法、多叉树】,知识拓展:深度优先搜索与广度优先搜索

题目描述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits "23" 输出…

Python爬虫项目 | 一、网易云音乐热歌榜歌曲

文章目录 1.文章概要1.1 实现方法1.2 实现代码1.3 最终效果 2.具体讲解2.1 使用的Python库2.2 代码说明2.2.1 创建目录保存文件2.2.2 爬取网易云音乐热歌榜单歌曲 2.3 过程展示 3 总结 1.文章概要 学习Python爬虫知识&#xff0c;实现简单的一个小案例&#xff0c;网易云音乐热…

消息中间件分类

消息中间件&#xff08;Message Middleware&#xff09;是一种在分布式系统中实现跨平台、跨应用通信的软件架构。它基于消息传递机制&#xff0c;允许不同系统、不同编程语言的应用之间进行异步通信。 常见的消息中间件类型包括&#xff1a; 1. JMS&#xff08;Java Message S…

GoogleCloud服务器的SSH连接配置

首先&#xff0c;Google的服务器默认是通过自带的SSH网页端连接的&#xff0c;比较麻烦和容易断开&#xff0c;不是很好用&#xff0c;常见的解决办法有两种一种是通过修改ssh的配置&#xff0c;添加密码的方式进行连接&#xff0c;一种是通过配置公钥进行连接。 密码连接之前有…

31.3 XOR压缩和相关的prometheus源码解读

本节重点介绍 : xor 压缩value原理xor压缩过程讲解xor压缩prometheus源码解读xor 压缩效果 xor 压缩value原理 原理:时序数据库相邻点变化不大&#xff0c;采用异或压缩float64的前缀和后缀0个数 xor压缩过程讲解 第一个值使用原始点存储计算和前面的值的xor 如果XOR值为0&…

【图像压缩感知】论文阅读:Content-Aware Scalable Deep Compressed Sensing

tips&#xff1a; 本文为个人阅读论文的笔记&#xff0c;仅作为学习记录所用。本文参考另一篇论文阅读笔记 Title&#xff1a; Content-Aware Scalable Deep Compressed Sensing Journal&#xff1a; TIP 2022 代码链接&#xff1a; https://github.com/Guaishou74851/CASNet…

Neo4j Desktop 和 Neo4j Community Edition 区别

Neo4j Desktop 和 Neo4j Community Edition 的主要区别在于它们的用途、功能以及安装和管理方式。以下是这两者的详细对比&#xff1a; 1. Neo4j Desktop Neo4j Desktop 是一个图形化的桌面应用程序&#xff0c;主要为开发人员和个人使用提供了一个便捷的环境来安装、管理和运…

DAY120java审计第三方组件依赖库挖掘FastjsonShiroLog4jH2DB

组件漏洞判断插件 一、Tmall_demo-master&#xff08;fastjson&#xff09; 1、配置文件查找安装组件 1、JSON.parse(json) 2、JSON.parseObject 2、找可控的变量 3、利用组件漏洞 poc:propertyJson{"type":"java.net.Inet4Address","val":&q…

要查看你的系统是 x64(64位)还是 x86(32位),可以按照以下步骤操作

文章目录 1. 通过“系统信息”查看系统架构2. 通过“设置”查看系统架构3. 通过命令提示符查看系统架构4. 通过 PowerShell 查看系统架构5. 通过文件资源管理器查看系统架构总结 要查看你的系统是 x64&#xff08;64位&#xff09;还是 x86&#xff08;32位&#xff09;&…

通过JS删除当前域名中的全部COOKIE教程

有时候需要通过JS来控制一下网站的登录状态&#xff0c;就例如:网站登出功能&#xff0c;我们可以直接通过JS将所有COOKIE删除&#xff0c;COOKIE删除之后&#xff0c;网站自然也就退出了。 那么今天我就给大家分享一段JS的函数&#xff0c;通过调用这段函数就可以实现删除COO…

在Ubuntu22.04上源码构建ROS noetic环境

Ubuntu22.04上源码构建ROS noetic 起因准备环境创建工作目录并下载源码安装编译依赖包安装ros_comm和rosconsole包的两个补丁并修改pluginlib包的CMakeLists的编译器版本编译安装ROS noetic和ros_test验证 起因 最近在研究VINS-Mono从ROS移植到ROS2&#xff0c;发现在编写feat…

C++ 中的string类

本文主要通过文档形式使用C中string类的常见接口进行介绍&#xff0c;然后我们自己实现一个string类 标准库中的string 使用库中的string类时&#xff0c;必须包含头文件&#xff1a;#include<string>, 以及 using namespace std string 构造函数 首先我们来看构造函数…