0 前言在咱们程序员或 DBA 的工作中,写 SQL 并执行就像吃一口饭一样平时。应用黑屏客户端时,往往要面对 SQL 编写艰难、谬误难以疾速辨认、查问后果不易读等问题,因而通常会抉择一款图形化化工具以调试、执行 SQL。那么你是否会好奇,当咱们应用可视化的开发者工具执行一条 SQL 时,从点击执行,到展现后果、查问执行打算这个过程,这条 SQL 经验了什么呢?如果点击执行很久能力失去后果,这两头又是哪个阶段出了问题呢?ODC 作为数据库开发者工具,致力于为用户提供更高效、更易用的 SQL 执行与诊断计划,在 4.1.0 版本,对 SQL 执行阶段的耗时也做了进一步的细化展现,以不便用户更清晰的理解 SQL 耗时详情。本文以 OB-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 messageOceanBase 数据库提供了字典视图 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_idTENANT_IDNUMBER(38) 发送申请的租户 IDREQUEST_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 的权限治理模型,敬请期待。