OceanBase初体验之查看OceanBase的执行计划
前置条件
- 包含obd和obclient的中控机
- OceanBase 测试集群
- 独立的测试租户
- BenchmarkSQL 工具(可选)
为了能够方面的查看复杂SQL的执行计划,我们先用TPCC模拟一些数据库负载。
模拟数据库负载
obd里面已经集成了tpcc测试工具,需要联网更新一下插件即可。如果机器不具备外网环境,需要提前下载BenchmarkSQL上传到测试机中。
BenchmarkSQL下载地址:https://github.com/meiq4096/benchmarksql-5.0
这里直接用obd里的tpcc,操作比较简单:
[ob@localhost ~]$ sudo yum install -y yum-utils
[ob@localhost ~]$ sudo yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBase.repo
[ob@localhost ~]$ sudo yum install obtpcc java
在前面新建的tt租户下跑一个10仓的负载,时间是5分钟:
[ob@localhost ~]$ obd test tpcc obtest --tenant=tt --warehouses 10 --run-mins 5
Get local repositories and plugins ok
Open ssh connection ok
Cluster status check ok
Connect obproxy(x.x.x.222:2883) ok
Connect obproxy(x.x.x.222:2883) ok
Optimize for stage build ok
Connect to tenant tt ok
Server check ok
Merge ok
Starting BenchmarkSQL LoadData
driver=com.mysql.jdbc.Driver
conn=jdbc:mysql://x.x.x.222:2883/test?rewriteBatchedStatements=true&allowMultiQueries=true&useLocalSessionState=true&useUnicode=true&characterEncoding=utf-8&socketTimeout=30000000&useSSL=false
user=root@tt
password=***********
warehouses=10
loadWorkers=1
fileLocation (not defined)
csvNullValue (not defined - using default 'NULL')
Worker 000: Loading ITEM
Worker 000: Loading ITEM done
Worker 000: Loading Warehouse 1
Worker 000: Loading Warehouse 1 done
Worker 000: Loading Warehouse 2
Worker 000: Loading Warehouse 2 done
Worker 000: Loading Warehouse 3
Worker 000: Loading Warehouse 3 done
Worker 000: Loading Warehouse 4
Worker 000: Loading Warehouse 4 done
Worker 000: Loading Warehouse 5
Worker 000: Loading Warehouse 5 done
Worker 000: Loading Warehouse 6
Worker 000: Loading Warehouse 6 done
Worker 000: Loading Warehouse 7
Worker 000: Loading Warehouse 7 done
Worker 000: Loading Warehouse 8
Worker 000: Loading Warehouse 8 done
Worker 000: Loading Warehouse 9
Worker 000: Loading Warehouse 9 done
Worker 000: Loading Warehouse 10
Worker 000: Loading Warehouse 10 done
create index ok
finish build ok
check data ok
Optimize for stage test ok
Connect to tenant tt ok
Merge ok
14:20:27,866 [main] INFO jTPCC : Term-00,
14:20:27,869 [main] INFO jTPCC : Term-00, +-------------------------------------------------------------+
14:20:27,869 [main] INFO jTPCC : Term-00, BenchmarkSQL v5.0
14:20:27,869 [main] INFO jTPCC : Term-00, +-------------------------------------------------------------+
14:20:27,869 [main] INFO jTPCC : Term-00, (c) 2003, Raul Barbosa
14:20:27,869 [main] INFO jTPCC : Term-00, (c) 2004-2016, Denis Lussier
14:20:27,872 [main] INFO jTPCC : Term-00, (c) 2016, Jan Wieck
14:20:27,872 [main] INFO jTPCC : Term-00, +-------------------------------------------------------------+
14:20:27,872 [main] INFO jTPCC : Term-00,
14:20:27,872 [main] INFO jTPCC : Term-00, db=oceanbase
14:20:27,872 [main] INFO jTPCC : Term-00, driver=com.mysql.jdbc.Driver
14:20:27,872 [main] INFO jTPCC : Term-00, conn=jdbc:mysql://x.x.x.222:2883/test?rewriteBatchedStatements=true&allowMultiQueries=true&useLocalSessionState=true&useUnicode=true&characterEncoding=utf-8&socketTimeout=30000000&useSSL=false
14:20:27,872 [main] INFO jTPCC : Term-00, user=root@tt
14:20:27,872 [main] INFO jTPCC : Term-00,
14:20:27,872 [main] INFO jTPCC : Term-00, warehouses=10
14:20:27,873 [main] INFO jTPCC : Term-00, terminals=100
14:20:27,874 [main] INFO jTPCC : Term-00, runMins=5
14:20:27,874 [main] INFO jTPCC : Term-00, limitTxnsPerMin=0
14:20:27,874 [main] INFO jTPCC : Term-00, terminalWarehouseFixed=true
14:20:27,874 [main] INFO jTPCC : Term-00,
14:20:27,874 [main] INFO jTPCC : Term-00, newOrderWeight=45
14:20:27,875 [main] INFO jTPCC : Term-00, paymentWeight=43
14:20:27,875 [main] INFO jTPCC : Term-00, orderStatusWeight=4
14:20:27,875 [main] INFO jTPCC : Term-00, deliveryWeight=4
14:20:27,875 [main] INFO jTPCC : Term-00, stockLevelWeight=4
14:20:27,875 [main] INFO jTPCC : Term-00,
14:20:27,875 [main] INFO jTPCC : Term-00, resultDirectory=my_result_%tY-%tm-%td_%tH%tM%tS
14:20:27,875 [main] INFO jTPCC : Term-00, osCollectorScript=./misc/os_collector_linux.py
14:20:27,875 [main] INFO jTPCC : Term-00,
14:20:27,891 [main] INFO jTPCC : Term-00, copied /home/ob/tmp/props.oceanbase to my_result_2024-03-17_142027/run.properties
14:20:27,891 [main] INFO jTPCC : Term-00, created my_result_2024-03-17_142027/data/runInfo.csv for runID 1
14:20:27,891 [main] INFO jTPCC : Term-00, writing per transaction results to my_result_2024-03-17_142027/data/result.csv
14:20:27,892 [main] INFO jTPCC : Term-00, osCollectorScript=./misc/os_collector_linux.py
14:20:27,892 [main] INFO jTPCC : Term-00, osCollectorInterval=1
14:20:27,892 [main] INFO jTPCC : Term-00, osCollectorSSHAddr=null
14:20:27,892 [main] INFO jTPCC : Term-00, osCollectorDevices=null
14:20:27,953 [main] INFO jTPCC : Term-00,
14:20:28,239 [main] INFO jTPCC : Term-00, C value for C_LAST during load: 192 Term-00, 14:25:29,121 [Thread-5] INFO jTPCC : Term-00, mTOTAL: 1116984 Memory Usage: 95MB / 730MB 14:25:29,121 [Thread-5] INFO jTPCC : Term-00, 14:25:29,121 [Thread-5] INFO jTPCC : Term-00, Measured tpmC (NewOrders) = 15185.13
14:25:29,121 [Thread-5] INFO jTPCC : Term-00, Measured tpmTOTAL = 33746.42
14:25:29,121 [Thread-5] INFO jTPCC : Term-00, Session Start = 2024-03-17 14:20:28
14:25:29,121 [Thread-5] INFO jTPCC : Term-00, Session End = 2024-03-17 14:25:29
14:25:29,122 [Thread-5] INFO jTPCC : Term-00, Transaction Count = 168883
TPC-C Result
Measured tpmC (NewOrders) : 15185.13
Measured tpmTOTAL : 33746.42
Session Start : 2024-03-17 14:20:28
Session End : 2024-03-17 14:25:29
Transaction Count : 168883
Recover ok
Trace ID: eeb13702-e424-11ee-aaa8-1c697a639d50
If you want to view detailed obd logs, please run: obd display-trace eeb13702-e424-11ee-aaa8-1c697a639d50
手动部署 BenchmarkSQL 主要步骤:
git clone https://github.com/obpilot/benchmarksql-5.0.git
cd benchmarksql-5.0/run
vi props.ob # 修改成实际的连接信息,设置主要运行参数
sh runSQL.sh props.ob sql.oceanbase/tableCreates.sql # 创建表结构
sh runSQL.sh props.ob sql.oceanbase/indexCreates.sql # 创建索引
sh runLoader.sh props.ob # 装载数据
sh runBenchmark.sh props.ob # 执行测试
跑tpcc时数据库的负载情况如下:

查找 TOP SQL
查询某段时间内请求次数排在 TOP N 的 SQL:
SELECT/*+ PARALLEL(15)*/ SQL_ID,PLAN_ID, COUNT(*) AS QPS, AVG(t1.elapsed_time) RT
FROM oceanbase.GV$OB_SQL_AUDIT t1 WHERE tenant_id = 1002 AND
IS_EXECUTOR_RPC = 0 AND time_to_usec(DATE_SUB(current_timestamp, INTERVAL 10 MINUTE) ) AND
request_time < time_to_usec (now())
GROUP BY t1.sql_id ORDER BY QPS DESC LIMIT 10;
+----------------------------------+---------+------+----------+
| SQL_ID | PLAN_ID | QPS | RT |
+----------------------------------+---------+------+----------+
| A460265EC2F0763A15DD27CE9E4E2200 | 4518 | 4771 | 59.6087 |
| 7229213613983BC5FDA15AD11EC70D01 | 3206 | 1440 | 340.2958 |
| E1F2BDA1D7391B757859ED3704E5AFB7 | 3213 | 1440 | 125.9278 |
| 2B5697196EDFE9E97FA3384F581178F5 | 3214 | 1440 | 87.7139 |
| FFFCA4D67EA0A788813031B8BBC3B329 | 0 | 301 | 34.6412 |
| 54B5A5861DAF78F52D9ADFBEE83D35B5 | 3202 | 152 | 94.4276 |
| 7F4A525CC8F849F6527F4911CC4BC348 | 3189 | 152 | 121.2303 |
| BB01ECB7605AE31CBC65E6949D84B235 | 3195 | 152 | 220.9079 |
| E86A0CA8BE3F21A2FBC9F1F9855075A1 | 3184 | 152 | 824.8158 |
| FC3FED8CCB2946DE54F1C5BA3656023C | 3181 | 152 | 501.9671 |
+----------------------------------+---------+------+----------+
10 rows in set (0.012 sec)
查询某段时间内平均 执行时间 排在 TOP N 的 SQL(可根据执行时间定位慢SQL):
SELECT/*+ PARALLEL(15)*/ SQL_ID,PLAN_ID, COUNT(*) AS QPS, AVG(t1.elapsed_time) RT
FROM oceanbase.GV$OB_SQL_AUDIT t1
WHERE tenant_id = 1002 AND IS_EXECUTOR_RPC = 0
AND request_time > time_to_usec(DATE_SUB(current_timestamp, INTERVAL 10 MINUTE) )
GROUP BY t1.sql_id ORDER BY RT DESC LIMIT 10;
根据sql_id找到对应的SQL文本:
obclient [(none)]> select query_sql from oceanbase.GV$OB_PLAN_CACHE_PLAN_STAT where sql_id='A460265EC2F0763A15DD27CE9E4E2200';
+---------------------------------------------------------------------------+
| query_sql |
+---------------------------------------------------------------------------+
| SELECT i_price, i_name, i_data FROM bmsql_item WHERE i_id = 14972 |
+---------------------------------------------------------------------------+
1 row in set (0.005 sec)
分析执行计划
我们获取平均执行时间最长的三条SQL,分析他们的实际执行计划和解析执行计划。
先找出TOP SQL:
obclient [(none)]> SELECT/*+ PARALLEL(15)*/ SQL_ID,PLAN_ID, COUNT(*) AS QPS, AVG(t1.elapsed_time) RT
-> FROM oceanbase.GV$OB_SQL_AUDIT t1
-> WHERE tenant_id = 1002 AND IS_EXECUTOR_RPC = 0
-> AND request_time > time_to_usec(DATE_SUB(current_timestamp, INTERVAL 10 MINUTE) )
-> GROUP BY t1.sql_id ORDER BY RT DESC LIMIT 3;
+----------------------------------+---------+------+------------+
| SQL_ID | PLAN_ID | QPS | RT |
+----------------------------------+---------+------+------------+
| 89B757D18634B472A21A0EB8EB83ECE3 | 4035 | 1 | 11747.0000 |
| F59A700FA168324279B0DBC25E19760F | 3217 | 8 | 5686.6250 |
| C9FA41444B84AF63AD4FB24B9252F1A6 | 4025 | 7 | 2694.7143 |
+----------------------------------+---------+------+------------+
3 rows in set (0.012 sec)
第一条sql_id找出对应的SQL文本,再手动获取执行计划:
obclient [tpcc]> explain SELECT count(*) AS low_stock FROM ( SELECT s_w_id, s_i_id, s_quantity FROM bmsql_stock WHERE s_w_id = 4 AND s_quantity < 17 AND s_i_id IN ( SELECT ol_i_id FROM bmsql_district JOIN bmsql_order_line ON ol_w_id = d_w_id AND ol_d_id = d_id AND ol_o_id >= d_next_o_id - 20 AND ol_o_id < d_next_o_id WHERE d_w_id = 4 AND d_id = 9 ) ) ;
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
| ================================================================================ |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| -------------------------------------------------------------------------------- |
| |0 |SCALAR GROUP BY | |1 |269 | |
| |1 |└─HASH RIGHT SEMI JOIN | |15 |269 | |
| |2 | ├─SUBPLAN SCAN |VIEW1 |15 |24 | |
| |3 | │ └─NESTED-LOOP JOIN | |15 |24 | |
| |4 | │ ├─TABLE GET |bmsql_district |1 |3 | |
| |5 | │ └─DISTRIBUTED TABLE RANGE SCAN|bmsql_order_line|1 |21 | |
| |6 | └─TABLE RANGE SCAN |bmsql_stock |1035 |156 | |
| ================================================================================ |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256 |
| group(nil), agg_func([T_FUN_COUNT(*)]) |
| 1 - output(nil), filter(nil), rowset=256 |
| equal_conds([bmsql_stock.s_i_id = VIEW1.ol_i_id]), other_conds(nil) |
| 2 - output([VIEW1.ol_i_id]), filter(nil), rowset=256 |
| access([VIEW1.ol_i_id]) |
| 3 - output([bmsql_order_line.ol_i_id]), filter(nil), rowset=256 |
| conds(nil), nl_params_([bmsql_district.d_next_o_id(:0)]), use_batch=false |
| 4 - output([bmsql_district.d_next_o_id]), filter([bmsql_district.d_next_o_id > bmsql_district.d_next_o_id - 20]), rowset=256 |
| access([bmsql_district.d_next_o_id]), partitions(p0) |
| is_index_back=false, is_global_index=false, filter_before_indexback[false], |
| range_key([bmsql_district.d_w_id], [bmsql_district.d_id]), range[4,9 ; 4,9], |
| range_cond([bmsql_district.d_w_id = 4], [bmsql_district.d_id = 9]) |
| 5 - output([bmsql_order_line.ol_i_id]), filter(nil), rowset=256 |
| access([bmsql_order_line.ol_i_id]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([bmsql_order_line.ol_w_id], [bmsql_order_line.ol_d_id], [bmsql_order_line.ol_o_id], [bmsql_order_line.ol_number]), range(MIN ; MAX), |
| range_cond([bmsql_order_line.ol_w_id = 4], [bmsql_order_line.ol_d_id = 9], [bmsql_order_line.ol_o_id >= :0 - 20], [bmsql_order_line.ol_o_id < :0]) |
| 6 - output([bmsql_stock.s_i_id]), filter([bmsql_stock.s_quantity < 17]), rowset=256 |
| access([bmsql_stock.s_i_id], [bmsql_stock.s_quantity]), partitions(p0) |
| is_index_back=false, is_global_index=false, filter_before_indexback[false], |
| range_key([bmsql_stock.s_w_id], [bmsql_stock.s_i_id]), range(4,MIN ; 4,MAX), |
| range_cond([bmsql_stock.s_w_id = 4]) |
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
36 rows in set (0.088 sec)
它的真实执行计划:
select * from oceanbase.V$OB_PLAN_CACHE_PLAN_EXPLAIN where tenant_id=1002 and plan_id=3217 ;

执行计划重要信息:
- OPERATOR,算子的名称,比如全表扫描TABLE SCAN,真实执行计划会加上
PHY_前缀 - NAME,算子操作的对象名称,比如表名、索引名等
- ROWS,真实执行计划里面代表实际数据行数,explain里面代表估算的行数(EST.ROWS)
- COST,算子执行时间,单位是微秒,explain里面的EST.TIME为估算时间
- PROPERTY,算子执行的详细过程
这里在查询执行计划时有一个坑要注意,oceanbase.V$OB_PLAN_CACHE_PLAN_EXPLAIN视图只能在SQL执行的observer节点上查询,因为PLAN CACHE是按节点缓存的,通过obproxy登录的话往往查不到想要的数据,要直连observer。
OceanBase初体验之查看OceanBase的执行计划的更多相关文章
- SQL Server如何查看存储过程的执行计划
有时候,我们需要查看存储过程的执行计划,那么我们有什么方式获取存储过程的历史执行计划或当前的执行计划呢? 下面总结一下获取存储过程的执行计划的方法. 1:我们可以通过下面脚本查看存储过程的执行计划,但 ...
- PL/SQL Developer 查看查询的执行计划
https://zhuanlan.zhihu.com/p/65771352 通过 PL/SQL Developer 查看查询的执行计划 1 什么是执行计划 执行计划是一条查询语句在 Oracle 中的 ...
- mysql explain 查看sql语句执行计划概述
mysql explain 查看sql语句执行计划概述 id:选择标识符select_type:表示查询的类型.table:输出结果集的表partitions:匹配的分区type:表示表的连接类型po ...
- 查看Oracle SQL执行计划的常用方式
在查看SQL执行计划的时候有很多方式 我常用的方式有三种 SQL> explain plan for 2 select * from scott.emp where ename='KING'; ...
- 查看oracle的执行计划
基于ORACLE的应用系统很多性能问题,是由应用系统SQL性能低劣引起的,所以,SQL的性能优化很重要,分析与优化SQL的性能我们一般通过查看该SQL的执行计划,本文就如何看懂执行计划,以及如何通过分 ...
- [转] 多种方法查看Oracle SQL执行计划
本文转自:http://falchion.iteye.com/blog/616234 一.在线查看执行计划表 如果PLAN_TABLE表不存在,执行$ORACLE_HOME/rdbms/admin/u ...
- 详细查看数据库SQL执行计划
DBCC DROPCLEANBUFFERS 清除数据缓存DBCC FREEPROCCACHE 清除执行计划缓存 SET SHOWPLAN_XML ON 此语句导致 SQL Server 不执行 Tr ...
- [转]使用mysql profiles 来查看sql 语句执行计划
From : http://blog.csdn.net/radkitty/article/details/4632289 要使用该功能,mysql的版本必须在5.0.37版本以上.否则只能使用expl ...
- 使用explain查看mysql查询执行计划
explain语句: 字段解释: type: all(全表扫描) ref() possible_keys: 预测使用什么列做为索引 key: 实际使用的key ...
- 查看ORACLE的实际执行计划
ORACLE的执行计划分为预估执行计划和实际执行计划.其中,你用Toad.PL/SQL Developer.SQL Developer.EXPLAIN PLAN FOR或者SET ATUOTRACE ...
随机推荐
- STM32 SPI DMA 源码解析及总结
一 前言 最近在调试stm32的SPI时候i,遇到了一个非常诡异的问题.中间花费了不少时间才把问题搞定.这中间暴露的问题值得反思.借此机会,还是梳理一下stm32的SPI的代码做一个总结吧. 二 初始 ...
- 「AntV」基于众源轨迹数据的三维路网生成与L7可视化
1. 引言 L7 地理空间数据可视分析引擎是一种基于 WebGL 技术的地理空间数据可视化引擎,可以用于实现各种地理空间数据可视化应用.L7 引擎支持多种数据源和数据格式,包括 GeoJSON.CSV ...
- 记录-JS简单实现购物车图片局部放大预览效果
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.实现效果 二.代码实现 代码不多,先看一下 HTML 里面结构很简单,初始化 MagnifyingGlass 对象来关联一个 IMG ...
- C# 二维码生成、识别,去除白边、任意颜色
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 可视化学习:实现Canvas图片局部放大镜
前言 最近我在可视化课程中学习了如何在Canvas中利用像素处理来实现滤镜效果,在这节课程的结尾留了一道局部放大镜的题目,提示我们用像素处理的方式去实现这个效果,最终实现随着鼠标移动将图片局部放大,本 ...
- KingbaseES使用sys_backup.sh脚本init初始化配置文件常见错误处理
KingbaseES使用sys_backup.sh脚本init初始化配置文件常见错误处理: 一.sys_backup.sh脚本按照如下顺序寻找初始化配置文件: [kingbase@postgres ~ ...
- 【已解决】mybatis注解@Param失效,无法获取到值(org.apache.ibatis.binding.BindingException: Parameter 'policy' not found. Available parameters are [arg1, arg0, param1, param2])
案发现场: 传递的参数是一个实体类 PolicyDictionary 此时我无法拿到数据: 解决思路一(不推荐) 删去@Param注解,使用mybatis默认的参数顺序: 不使用@param注解传递多 ...
- 第十三届蓝桥杯大赛软件赛省赛【Java 大学B 组】试题C: 字符统计
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String args[]) { 5 Sca ...
- 提升系统管理:监控和可观察性在DevOps中的作用
在不断发展的DevOps世界中,深入了解系统行为.诊断问题和提高整体性能的能力是首要任务之一.监控和可观察性是促进这一过程的两个关键概念,为系统的健康和性能提供了宝贵的可见性.虽然这些术语经常可以互换 ...
- ArrayList,LinkedList,Vector三者的区别
List 中元素是有序的,元素可以重复,因为该集合体有索引 ArrayList: 底层数据结构是数组,查询快,增删慢. 线程不安全,效率高. 当元素放满了后,默认以原长度的 50%+1 的长度加长集合 ...