如何用分布式数据库解决慢查询问题

当使用MySQL时,我们不可避免地会遇到许多与慢查询相关的问题。

为了解决这些慢SQL的问题,我们通常需要投入大量的精力去研究执行计划、考虑合适的索引策略、精心改写SQL语句,甚至可能需要调整程序逻辑。然而,针对特定SQL的优化往往既复杂又具有挑战性,而且存在许多原因,即使经过多次尝试和优化,也可能无法取得显著的效果。

慢查询产生的典型场景

下面是2个典型的慢查询场景,大家在日常写SQL和优化SQL的过程中应该会有感受:

场景一:大表

这是MySQL的经典问题。MySQL早期有单表数据量不能超过2000W的说法,虽然有点夸张,不过对于MyQL中千万级,乃至过亿的表,哪怕对这种表的查询建了索引,索引的B+树也会很深,查询速度确实很受影响,从而形成慢SQL。

一些有经验的开发会考虑给这张表加分区,通过合理拆分,来降低每个分区对应B+树索引的深度,从而提升执行性能。但MySQL毕竟是一个单机库,各个分区共享的还是一份硬件资源;而如果想突破单机的限制,就要考虑做分库,而那又是一个更复杂的问题,涉及到整个数据库用法和结构的大调整。

场景二:多表连接。这也是让很多研发头痛的问题,类似下面这类SQL:

select ... 

from t1 --100行

left join t2 --100000行

on t1.c1=t2.c1

left join t3 --100行

on t1.c1=t3.c1

left join t4 --100行

on t1.c1=t4.c1

order by t1.c1 limit 1000;

在这个例子中, 4 张表做连接 T1、T2、T3、T4,其中 T2 是大表,其它都是小表,如果严格按照连接次序来做,T1 跟 T2 连接,再跟 T3、T4 连接,最大的表T2就过早进行了合并,导致结果集特别大,整个SQL开销相对较高。

如果要优化慢查询的话,就要改写SQL,把T2挪到最后来连接,这样整个SQL的代价就会小很多了,但很多时候这是跟我们业务开发的逻辑是违背的。很多场景下,修改SQL都是非常麻烦的一件事。

其实自适应调整表连接顺序应该是数据库能做到的,这步一般被称为“SQL改写”,但因为MySQL当前的优化器更多是基于规则的模型,所以通常情况是做不到这点的。

为什么MySQL的大SQL能力比较差?

因为MySQL社区主要还是将MySQL定位为一个纯粹OLTP(Online Transaction Processing,联机交易处理)型的开源数据库。这个定位使得MySQL的迭代发版,侧重于提升单核性能、加强事务处理能力等,而对于大数据量、复杂查询类的偏OLAP(Online Analytical Processing,联机事务处理)场景,MySQL发展缓慢。

举个例子:在MySQL 8.0.14前,MySQL是没有并行执行能力的。也就是说MySQL对每条SQL最多只能使用CPU的一个核来处理。而并行执行可以将一个 SQL 查询任务分成多个子任务,并允许这些子任务在多个处理器上同时运行,以提高整个查询任务的执行效率。对于上文的慢查询场景一而言,并行执行就可以极快加速这种场景的查询效率。虽然MySQL自8.0.14版本开始支持并行执行,但目前仅在select count(*)等有限场景下生效,且必须手动配置参数。因此目前MySQL还不支持大部分场景的并行执行,从根本上解决复杂查询的问题。

用分布式数据库解决慢查询问题

针对这些挑战,OceanBase作为一款原生分布式的HTAP(Hybrid Transactional/Analytical Processing)数据库,对大规模查询场景的处理上进行了重点的优化。如果您也在寻求解决慢SQL查询的方案,不妨尝试一下用分布式数据库OceanBase从根本上来解决这个问题。

OceanBase在大查询场景的主要技术点有:

1、并行执行

OceanBase有非常成熟的并行执行能力,可以对普通查询、DDL、DML操作都进行并行执行,并且可以自动/手动灵活选取并行度。这可以使得开发者通过少量CPU的代价,简单、直接的使原本运行较慢的SQL性能快上几倍,对于大SQL问题有立竿见影的解决效果。

可以通过下面两个参数来开启并设置自动并行:

#开启并行

set global parallel_degree_policy = AUTO; 

#设置基表最大扫描时间,单位为ms,默认为1000ms;您可以视情况调大或调小这个值,这里把这个参数改为100ms,即基表扫描时间超过100ms,则开启并行执行。

set global parallel_min_scan_time_threshold = 100;

2、分库分表

如同前文MySQL的场景一中所提到的,解决大数据量表查询性能问题的一个解法是分库分表,但MySQL分库分表有很高的改造成本。而OceanBase是一款原生的分布式数据库,OceanBase中的分区是一个独立的存储、高可用、事务的单位,这意味着OceanBase同一张表的不同分区可以分布在不同的服务器上,从而利用多机性能大大加快大表查询速度。同时OB的原生分布式能力,也可以使应用程序像使用一个单机数据库一样使用分布式的OB,没有业务改造成本。

3、多表连接次序优化

对于前文的场景二,业务上是比较难判断怎么调整表连接的顺序更好的,而OceanBase 实现了一套完备的连接枚举算法,整体优化逻辑是基于代价的,可以灵活调整内连接和外连接的次序,可以调整外连接、反连接、半连接,甚至还可以改变一个外连接的连接类型,把它变成内连接或反连接等,可以做到场景自动优化。像场景二的例子,在OB中自然就会优化成,t1跟t3连接,再跟t4连接,最后再跟t2连接,从而使得SQL执行性能快了近百倍。很多在MySQL中需要反复改写、调优的SQL,在OB中自然跑出来就是最优的执行计划。

4、子查询场景优化

子查询也是很常见的性能问题,并且不同于多表连接,子查询通常比较难改写,往往会造成执行很慢。OceanBase 查询改写模块,实现了丰富的子查询优化策略,只要不是嵌套非常深的子查询,都可以把它变成连接,变成连接后,就成了连接枚举的问题,可以采取不同的连接算法去优化它。

5、大表聚合场景优化

大表聚合也是一个经典的场景,比如我们要汇总一年的营业额数据,就有可能用到下面的SQL:

SELECT year(sold_date) AS yearDate,  code, name, SUM(value0) as total_value FROM t where sold_date>='2023-01-01' and sold_date<'2023-12-31' GROUP BY year(sold_date), code, name;

针对这种场景,OB有一种优化能力称作预聚合,就是把大表的数据拆成多份,每个线程分别做分组聚合,然后线程交换数据继续聚合,全部聚合完后再做一次汇总。比如把示例中t表分为100组,每组按year(sold_date), code, name分别聚合,再最后汇总。

预聚合配合并行执行,往往可以取得几倍的性能提升。但这种优化并不一定是好效果的,假如一共10亿条数据,不同的year(sold_date), code, name租户就有5亿种,那么区分度就太低了,预聚合甚至是一个反优化。

OceanBase 面对大表聚合场景,是让执行引擎变得更聪明,不在优化器层面去做决策,而是交给执行层,执行根据计算过程中的实际情况,去决定做不做预聚合优化。

当前OceanBase 对各种场景基本都支持了这个优化,包括分组、去重、窗口函数,都可以灵活判断是否做预聚合。

6、TP 与 AP隔离,避免互相影响

对于数据库来说,相比于单条复杂大查询,让大量的 DML 和短查询尽快返回更有意义。为了避免一条大查询阻塞大量简单请求而导致系统吞吐量暴跌,避开分库分表的查询性能局限,当大查询和短请求同时争抢 CPU 时,OceanBase 会限制大查询的 CPU 使用。当一个线程执行的 SQL 查询耗时太长,这条查询就会被判定为大查询,一旦判定为大查询,就会进入大查询队列,然后执行大查询的线程会等在一个 Pthread Condition 上,为其它的租户工作线程让出 CPU 资源。

通过这些技术能力,可以使得原本在MySQL中执行时间超过1s的慢SQL,在OceanBase中获得显著的性能提升。

如果大家希望体验分布式数据库OceanBase在复查查询的性能,可以在OceanBase官网开通365天的免费试用。1核4G的OceanBase租户实例就可以体验查询性能,如果还需要体验OceanBase的其他特性,也可以申请企业版的集群实例。产品中有相关的新手教程引导,也请注意通过上文中的方法打开并行执行。

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

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

相关文章

pipx安装提示找不到包

执行&#xff1a; pipx install --include-deps --force "ansible6.*"WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by NewConnectionError(<pip._vendor.urllib3.connection.HTTPSConnection …

VMware 17虚拟Ubuntu 22.04设置共享目录

VMware 17虚拟Ubuntu 22.04设置共享目录 共享文件夹挂载命令&#xff01;&#xff01;&#xff01;<font colorred>配置启动自动挂载Chapter1 VMware 17虚拟Ubuntu 22.04设置共享目录一、卸载老版本二、安装open-vm-tools<font colorred>三、配置启动自动挂载四、添…

uniapp ios app以framwork形式接入sentry

一、下载Sentry mac终端输入&#xff1a;vim Podfile修改Podfile: platform :ios, 11.0 target YourApp douse_frameworks! # This is importantpod Sentry, :git > https://github.com/getsentry/sentry-cocoa.git, :tag > 8.40.1 end执行&#xff1a;pod install下载…

Python用CEEMDAN-LSTM-VMD金融股价数据预测及SVR、AR、HAR对比可视化

全文链接&#xff1a;https://tecdat.cn/?p38224 分析师&#xff1a;Duqiao Han 股票市场是一个复杂的非线性系统&#xff0c;股价受到许多经济和社会因素的影响。因此&#xff0c;传统的线性或近线性预测模型很难有效、准确地预测股票指数的价格趋势。众所周知&#xff0c;深…

Linux kvm环境搭建

1.1 安装KVM虚拟机 #系统是否支持KVM虚拟化 [rootjztserver01 ~]# cat /proc/cpuinfo | egrep vmx|svm [rootjztserver01 ~]# egrep (vmx|svm) /proc/cpuinfo |wc -l #关闭selinux&#xff1b;设置selinux立即生效 [rootjztserver01 ~]# vi /etc/sysconfig/selinux [rootjztse…

2020年计挑赛往届真题(C++)

因为17号要开赛了&#xff0c;甚至是用云端编辑器&#xff0c;debuff拉满&#xff0c;只能临时抱佛脚了 各个选择题的选择项我就不标出来了&#xff0c;默认ABCD排&#xff0c;手打太麻烦了 目录 单选题&#xff1a; 1.阅读以下语句:double m0;for(int i3;i>0;i--)m1/i;…

2 的幂算法

给你一个整数 n&#xff0c;请你判断该整数是否是 2 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在一个整数 x 使得 n 2x &#xff0c;则认为 n 是 2 的幂次方。 示例 1&#xff1a; 输入&#xff1a;n 1 输出&#xff1a;tr…

ubuntu20.04默认的python3.8升级到python3.10

Python 3.8 于 2019 年 10 月发布&#xff0c;距今已有五年时间。2024 年 10 月是 Python 3.8 版本发布的最后一个月&#xff0c;从 2024 年 10 月开始&#xff0c;如果存在安全错误&#xff0c;Python 开发团队将不会修复该错误。有必要把python3.8升级python3.10。 新加apt源…

CTF-RE 从0到N: windows反调试-获取Process Environment Block(PEB)信息来检测调试

在Windows操作系统中&#xff0c;Process Environment Block (PEB&#xff0c;进程环境块) 是一个包含特定进程信息的数据结构。它可以被用于反调试中 如何获取PEB指针&#xff1f; 在Windows操作系统中&#xff0c;获取PEB指针的常见方法主要有以下几种。&#xff1a; 1. 使…

数据结构 ——— 层序遍历链式二叉树

目录 链式二叉树示意图​编辑 何为层序遍历 手搓一个链式二叉树 实现层序遍历链式二叉树 链式二叉树示意图 何为层序遍历 和前中后序遍历不同&#xff0c;前中后序遍历链式二叉树需要利用递归才能遍历 而层序遍历是非递归的形式&#xff0c;如上图&#xff1a;层序遍历的…

RHEL/CENTOS 7 ORACLE 19C-RAC安装(纯命令版)

一 首先需要安装两个CENTOS 7虚拟机(此处省略)。 由于我们是要安装ORCLE-RAC双节点集群所以至少每个CENTOS虚拟机上需要两块网卡&#xff0c;并且两块网卡都是HOST-ONLY具体步骤请看视频一《为虚拟机添加网卡》 这里大家需要注意的是&#xff0c;我们需要绑定两台机器的IP一共…

DevOps工程技术价值流:加速业务价值流的落地实践与深度赋能

DevOps的兴起&#xff0c;得益于敏捷软件开发的普及与IT基础设施代码化管理的革新。敏捷宣言虽已解决了研发流程中的诸多挑战&#xff0c;但代码开发仅是漫长价值链的一环&#xff0c;开发前后的诸多问题仍亟待解决。与此同时&#xff0c;虚拟化和云计算技术的飞跃&#xff0c;…

ubuntu24.04设置开机自启动Eureka

ubuntu24.04设置开机自启动Eureka 之前我们是在/root/.bashrc的文件中增加了一条命令 nohup java -jar /usr/software/eurekaServer-auth-prd-03.jar > /usr/software/log.log 2>&1 &但上面这条命令只有在登录root的用户时&#xff0c;才会执行&#xff0c;如果…

python json详解

json 是 Python 中用于处理 JSON 数据的标准库。JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人类阅读和编写&#xff0c;同时也易于机器解析和生成。Python 的 json 模块提供了将 Python 对象与 JSON 数据相互转换的功…

WPS宏编辑器开发,单元格内容变更自动触发事件

WPS中Excel的“触发器” 写在前面宏的开发1、切换宏编辑器开发环境2、小练习&#xff1a;自定义函数3、完成功能需求&#xff1a;单元格内容变更自动触发事件 总结 写在前面 我先生用EXCEL做了一张学生存款表。设计得很简单&#xff0c;A学生已存款X元&#xff0c;A学生再次存…

新版Apache Tomcat ⽬目录文件讲解(笔记)

简介&#xff1a;Tomcat⽬目录⽂文件讲解 bin &#xff08;关注&#xff09; 启动和关闭tomcat脚本 startup.sh/startup.bat (Linux平台或Mac上的启动脚本/Windows平台上的启动脚本) shutdown.sh/shutdown.bat (Linux平台或Mac上的关闭脚本/Windows平台上的关闭脚本) conf&am…

java Arrays 详解

Java Arrays 类详解 Arrays 是 Java 中一个专门用于操作数组的工具类&#xff0c;位于 java.util 包中。它提供了多种用于数组操作的方法&#xff0c;例如排序、搜索、填充、比较、转换等。 1. 常用方法分类 1.1 排序 方法描述Arrays.sort(array)对数组进行升序排序&#xf…

Go 语言已立足主流,编程语言排行榜24 年 11 月

Go语言概述 Go语言&#xff0c;简称Golang&#xff0c;是由Google的Robert Griesemer、Rob Pike和Ken Thompson在2007年设计&#xff0c;并于2009年11月正式宣布推出的静态类型、编译型开源编程语言。Go语言以其提高编程效率、软件构建速度和运行时性能的设计目标&#xff0c;…

一个win32 / WTL下多线程库(CThread类)的使用心得

说是多线程库&#xff0c;其实就是一个单独的.h文件&#xff0c;可以方便的放入WTL/win32工程中。 下载地址&#xff1a;CThread. 里面也简单介绍了 用法。 具体用法&#xff0c;首先自定义一个子线程类继承CThreadImpl<T>&#xff0c;注意他是个模板类。 class CMySu…

Kettle配置数据源错误“Driver class ‘org.gjt.mm.mysql.Driver‘ could not be found”解决记录

问题描述 错误提示&#xff1a;“Driver class ‘org.gjt.mm.mysql.Driver’ could not be found, make sure the ‘MySQL’ driver (jar file) is installed.” 原因分析&#xff1a; 根据错误提示是缺少了相关的数据源连接jar包。 解决方案&#xff1a; 安装对应的Mysql…