SQL性能优化 ——OceanBase SQL 性能调优实践分享(3)

2024-06-03 18:20

本文主要是介绍SQL性能优化 ——OceanBase SQL 性能调优实践分享(3),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

相比较之前的两篇《连接调优》和《索引调优》,本篇文章主要是对先前两篇内容的整理与应用,这里不仅归纳了性能优化的策略,也通过具体的案例,详细展示了如何分析并定位性能瓶颈的步骤。

SQL 调优

先给出性能优化方法和分析性能瓶颈步骤的文字描述:

性能优化的方法

  1. 开启并行执行等机制(简单),可以参考:《OceanBase 并行执行技术》。这篇博客内容过多(实际应该像性能调优系列拆成多篇发的),从 4.2 版本开始,OB 已经支持了 auto dop,如果用户不熟悉并行度的设置规则,可以设置 parallel_degree_policy 为 AUTO,让优化器帮忙自动选择合适的并行度,推荐使用。auto dop 的相关内容可以直接在上面这篇博客中搜索 parallel_degree_policy 关键字,或者参考官网文档。
  2. 创建合适的索引(简单),可以参考:《索引调优 —— OceanBase SQL 性能调优系列 1》。
  3. 调整连接方式(比较简单),可以参考:《连接调优 —— OceanBase SQL 性能调优系列 2》
  4. 调整连接顺序(难度较大),这里指的是:例如有 t1,t2,t3 三个表做连接, 假设 OB 的优化器认为 t1,t2 两个表先做连接,再与 t3 做连接,是一个比较好的计划。但是实际可能是 t1 和 t3 先做连接,再和 t2 做连接是更优的计划。此时可以通过 hint 告诉优化器正确的连接顺序来优化 SQL 的性能(参考官网文档),在一些复杂场景下,需要丰富的经验支持才能通过调整连接顺序来优化 SQL 执行效率,有兴趣的同学可以自行研究和尝试。
  5. 检查 OB 是否做了错误的查询改写 / 缺少合适的查询改写机制(难度较大)。

分析性能瓶颈的步骤

  1. 利用 SQL 执行计划去分析具体哪些步骤(哪几个算子)的执行时间慢。个人经验是可以通过把大 SQL 拆分成小 SQL 去分析这一步。
  2. 充分利用已有的脚本和工具来简化分析过程。这里我理解主要是通过一些字典视图,例如 oceanbase.GV$SQL_PLAN_MONITOR。

分析 SQL 性能瓶颈的例子

举一个真实的 SQL 性能分析和优化的例子:下面这条 SQL 执行了 2.43 秒,接下来开始分析性能瓶颈并进行优化。

1705634431

看到优化器生成计划是让 bbtr 表先与 cte 表做 merge join,再与 btr 表做 nest loop join。

1705634441

在上面的计划中,从 4 号算子到 8 号算子是三张表的 join 是这个计划最核心的部分,大概率也是性能的瓶颈点,我们先从这里开始分析。

=============================
|ID|OPERATOR           |NAME|
-----------------------------
|4 |NESTED-LOOP JOIN   |    |
|5 |├─MERGE JOIN       |    |
|6 |│  └─TABLE SCAN    |BBTR|
|7 |│  └─TABLE SCAN    |CTE |
|8 |└─TABLE GET        |BTR |
=============================

要分析出计划里哪里是瓶颈,首先得查一下每个表的数据量,先看最内层进行 merge join 的两张表 cte 和 bbtr,merge join 的代价是扫描出 cte 数据的代价 + 扫描出 bbtr 的代价 + 归并的代价:

cte 表在 7 号算子中的过滤条件是 cte.bpo_send_flag = '0',过滤之后返回数据量是 1638 行,扫描耗时 2.13 秒(这个时间明显不太对)。

1705634448

类似地,bbtr 表的数据在 6 号算子返回的数据量是 40 多万行,没有过滤条件,扫描耗费 0.19 秒。

1705634462

然后上层的 NLJ 要拿 merge join 的结果当做驱动表(左表),对右表 btr 进行 table get。

这条 SQL 一共执行了 2.43 秒,但仅仅是 merge join 中 cte 表的扫描代价就已经高达 2.13 秒了,所以这条 SQL 的瓶颈点就是 cte 表的扫描。

可以看到 cte 表上有一个过滤条件 bpo_send_flag = '0',所以我们可以通过在 cte 表的列 bpo_send_flag 上建一个索引来优化它的查询性能。如果考虑到计划中的 7 号算子还需要拿 cte 表中的 bpo_send_time 列和 claim_tpa_id 列的数据向上吐行,还可以考虑在(bpo_send_flag, bpo_send_time, claim_tpa_id)上创建联合索引来消除索引回表的性能消耗。

创建索引之后的计划预期大概会长这样:

=================================
|ID|OPERATOR           |NAME    |
---------------------------------
|4 |NESTED-LOOP JOIN   |        |
|5 |├─MERGE JOIN       |        |
|6 |│  └─TABLE SCAN    |BBTR    |
|7 |│  └─TABLE SCAN    |CTE(idx)|
|8 |└─TABLE GET        |BTR     |
=================================

假如上面排查下来发现 cte 表的扫描并不是瓶颈,那么应该做进一步的分析。例如尝试去单独去执行 bbtr 和 cte 两个表的连接,查看它的执行结果的行数和 btr 表的行数关系。4 号 NLJ 算子的左支返回的行数(merge join 结果的行)和右支返回的行数(btr 通过 8 号算子中 filter 过滤之后的行)如果没有明显的大小表关系(左支行数 / 右支行数 < 20),则意味着 4 号算子选择 Hash Join 的方式会比选择 NLJ 的方式更优。那么就可以通过使用 hint /*+ leading(bbtr cte btr) use_hash(btr) */ 来修改 4 号算子的连接方式,将 Nested_Loop Join 改成 Hash Join。

hint 和 outline

使用 hint 生成指定计划

官网上写的很详细,这里不再赘述,详见 OB 官网中的 hint 部分:

1705634481

使用 outline 进行计划绑定

官网上写的很详细,这里不再赘述,详见 OB 官网中的计划绑定部分:

1705634491

这篇关于SQL性能优化 ——OceanBase SQL 性能调优实践分享(3)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

MySQL数据库实现批量表分区完整示例

《MySQL数据库实现批量表分区完整示例》通俗地讲表分区是将一大表,根据条件分割成若干个小表,:本文主要介绍MySQL数据库实现批量表分区的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录一、表分区条件二、常规表和分区表的区别三、表分区的创建四、将既有表转换分区表脚本五、批量转换表为分区

宝塔安装的MySQL无法连接的情况及解决方案

《宝塔安装的MySQL无法连接的情况及解决方案》宝塔面板是一款流行的服务器管理工具,其中集成的MySQL数据库有时会出现连接问题,本文详细介绍两种最常见的MySQL连接错误:“1130-Hostisn... 目录一、错误 1130:Host ‘xxx.xxx.xxx.xxx’ is not allowed

JDK9到JDK21中值得掌握的29个实用特性分享

《JDK9到JDK21中值得掌握的29个实用特性分享》Java的演进节奏从JDK9开始显著加快,每半年一个新版本的发布节奏为Java带来了大量的新特性,本文整理了29个JDK9到JDK21中值得掌握的... 目录JDK 9 模块化与API增强1. 集合工厂方法:一行代码创建不可变集合2. 私有接口方法:接口

电脑系统Hosts文件原理和应用分享

《电脑系统Hosts文件原理和应用分享》Hosts是一个没有扩展名的系统文件,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应... Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应

sql语句字段截取方法

《sql语句字段截取方法》在MySQL中,使用SUBSTRING函数可以实现字段截取,下面给大家分享sql语句字段截取方法,感兴趣的朋友一起看看吧... 目录sql语句字段截取sql 截取表中指定字段sql语句字段截取1、在mysql中,使用SUBSTRING函数可以实现字段截取。例如,要截取一个字符串字

SQL Server身份验证模式步骤和示例代码

《SQLServer身份验证模式步骤和示例代码》SQLServer是一个广泛使用的关系数据库管理系统,通常使用两种身份验证模式:Windows身份验证和SQLServer身份验证,本文将详细介绍身份... 目录身份验证方式的概念更改身份验证方式的步骤方法一:使用SQL Server Management S

MySQL 字符串截取函数及用法详解

《MySQL字符串截取函数及用法详解》在MySQL中,字符串截取是常见的操作,主要用于从字符串中提取特定部分,MySQL提供了多种函数来实现这一功能,包括LEFT()、RIGHT()、SUBST... 目录mysql 字符串截取函数详解RIGHT(str, length):从右侧截取指定长度的字符SUBST

MySQL中的事务隔离级别详解

《MySQL中的事务隔离级别详解》在MySQL中,事务(Transaction)是一个执行单元,它要么完全执行,要么完全回滚,以保证数据的完整性和一致性,下面给大家介绍MySQL中的事务隔离级别详解,... 目录一、事务并发问题二、mysql 事务隔离级别1. READ UNCOMMITTED(读未提交)2

MySQL Workbench工具导出导入数据库方式

《MySQLWorkbench工具导出导入数据库方式》:本文主要介绍MySQLWorkbench工具导出导入数据库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录mysql Workbench工具导出导入数据库第一步 www.chinasem.cn数据库导出第二步