如何分析动态采样引起的计划不稳定 | OceanBase SQL 调优实践

这篇博客涉及两个知识点,一个是动态采样,另一个是 DAS 执行。

用户的问题和相关结论

我们看看用户在OceanBase 社区论坛发帖中提出的疑问及其所得出的结论。

问题:收集统计信息之前,为什么会出现计划不稳定的情况?

原帖详见:索引和统计信息问题咨询 - OceanBase - 社区问答- OceanBase社区-分布式数据库

结论:若尚未收集过统计信息,为了创建更优的执行计划,优化器会对表数据进行动态采样。动态采样是在计划生成阶段对数据库对象进行的采样,通过此方式估算行数,并将这些估算值用于代价计算模型中。由于动态采样过程中每次所选的样本数据块具有一定的随机性质,即便表中的数据保持不变,动态采样的结果也可能有所不同,因此可能导致生成不同的执行计划。

用户反馈的问题

下面是这个用户给的计划不稳定的例子,感兴趣的同学可以继续往下看:

第一个问题

用户问的第一个问题就是:为什么收集统计信息前,计划不稳定?

用户的环境信息:三 zone 三副本,各个副本的 leader 打散在三个分区上。

表定义长这样:

CREATE TABLE `test` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',`did` varchar(64) DEFAULT NULL COMMENT 'did',`dxm_uuid` varchar(64) DEFAULT NULL COMMENT 'uuid',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),UNIQUE KEY `unique_did_uuid` (`did`, `uuid`) BLOCK_SIZE 16384 GLOBAL,KEY `I_create_time` (`create_time`) BLOCK_SIZE 16384 LOCAL,KEY `I_update_time` (`update_time`) BLOCK_SIZE 16384 LOCAL
) REPLICA_NUM = 3partition by hash(id) PARTITIONS 30;

一张三十个分区的分区表,上面有三个索引,一个没有分区的 global index,两个和主表一样有三十个分区的 local index。

执行的 SQL 长这样,十分简单:

SELECTuuid
FROMtest
WHEREdid = ?
ORDER BYupdate_time DESC
LIMIT?

如果没有统计信息,根据不同的动态采样结果,显而易见,可能会出现两种计划。

第一种是走 I_update_time 这个 local index,好处是可以利用这个索引的有序性,优化 ORDER BY update_time DESC 这个排序的动作,消除了各个分区内的排序(个人理解三号算子的 top n sort 不需要真正进行 sort,只需要做 top n 就够了),计划长这样:

第二种是走 unique_did_uuid 这个 global index,好处是满足 did = ? 这个过滤条件的数据,可以在索引上被快速定位,计划长这样:

这里用户反馈的是:如果生成第一种走 I_update_time 这个 local index 的计划,就会慢。

如果生成第二种走 unique_did_uuid 这个 global index 的计划,就会快。

1718552204

因为没有统计信息,所以优化器只能根据动态采样得来的部分数据,算出这两种计划的代价,然后生成代价更低的计划。

即使表中的数据没有发生过变化,因为每次动态采样的数据因为有一定的随机性,会采样到不同的数据,所以可能导致生成的计划不稳定。如果采样到一批比较极端的不能代表整体数据特征的数据,就会导致生成不优的计划。

动态采样的介绍,详见官网链接:https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000000822131,咱们这里不多啰嗦。

第二个问题

用户问的第二个问题是:收集了统计信息之后,为什么就能稳定生成第二种更优的本地计划了?

这也是个有意思的问题,需要咱们再来重新回顾一遍问题的背景。

用户的环境信息:三 zone 三副本,各个副本的 leader 打散在三个分区上。

表定义长这样:

CREATE TABLE `test` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',`did` varchar(64) DEFAULT NULL COMMENT 'did',`dxm_uuid` varchar(64) DEFAULT NULL COMMENT 'uuid',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),UNIQUE KEY `unique_did_uuid` (`did`, `uuid`) BLOCK_SIZE 16384 GLOBAL,KEY `I_create_time` (`create_time`) BLOCK_SIZE 16384 LOCAL,KEY `I_update_time` (`update_time`) BLOCK_SIZE 16384 LOCAL
) REPLICA_NUM = 3partition by hash(id) PARTITIONS 30;

一张三十个分区的分区表,上面有三个索引,一个没有分区的 global index,两个和主表一样有三十个分区的 local index。

执行的 SQL 长这样,十分简单:

SELECTuuid
FROMtest
WHEREdid = ?
ORDER BYupdate_time DESC
LIMIT?

因为这条 SQL 涉及的表是分区表,各个分区的主副本都被打散在了不同的 zone 里,并且 SQL 的过滤条件又不包含分区键,所以 proxy 这个时候是没办法知道要怎么对这条 SQL 进行路由的。这时候 proxy 就会随机路由到任意一台节点上。

但是收集完统计信息之后,发现可以稳定选择走 unique_did_uuid 这个 global index,计划长这样:

看上去没有 remote xxx 算子和 exchange xxx 算子,不是远程计划和分布式计划,那么这就是个本地计划。

这个计划虽然是本地计划,但是实际也有数据的网络传输。因为 SQL 需要根据 update_time 列进行排序,global index 中并没有这个列的数据,所以过滤完之后,肯定还需要回主表(计划里也可以看到 is_index_back = true)去拿 update_time 列的值,一定还是会走网络的。

不过这个本地计划里的网络传输,和上一个计划有明确的 exchange 算子表示网络传输有所不同,这个计划里的网络传输被封到了一号算子里。一号算子是 DISTRIBUTED TABLE SCAN,含义是 TABLE SCAN 走了 DAS 执行。

大家可以简单地把 DAS 理解成是一种特殊场景下,对网络传输的优化。

DAS 不需要像 remote 或者 exchange 算子一样在网络中把复杂的 SQL 或者子计划在节点间传来传去,而是直接跟存储层交互,通过 RPC 拉取到存储层的数据。

DAS 一般会出现在简单的点查,或者全局索引回表中(刚好就是用户的场景,did = ? 是点查,并且还有全局索引的回表)。DAS 可以通过特殊的 RPC 和存储层直接进行远程数据的交互,所以可以减少在网络里传输 SQL 和子计划的开销。在这两种场景下,通过 DAS 的方式进行数据的网络传输,资源消耗是最小的。

DAS 执行的介绍详见官网链接:https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000217873,咱们依然不在这里多啰嗦。

我们以 proxy 转发 SQL 到 zone2 这台 observer 上为例,那么 zone2 上这台 observer 就会通过 DAS 发 RPC 拉取另外几个节点上的主表数据,进行全局索引回表。

我们以 proxy 转发 SQL 到 zone1 这台 observer 上为例,那么 zone1 上这台 observer 首先会通过 DAS 发 RPC 直接拉取 zone2 上 global index 主副本上的经过过滤之后的数据(过滤条件也一起下压过去了),然后再通过 DAS 发 RPC 拉取另外几个节点上的主表数据,进行全局索引回表。

所以无论 proxy 把 SQL 路由到哪个节点,这条 SQL 中网络传输的动作,都被封到一号 DISTRIBUTED TABLE SCAN 算子里了(一号算子通过 DAS 执行完成了全部的网络传输),因此可以生成稳定的计划。

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

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

相关文章

TypeScript 泛型讲解

如果说 TypeScript 是一门对类型进行编程的语言,那么泛型就是这门语言里的(函数)参数。本章,我将会从多角度讲解 TypeScript 中无处不在的泛型,以及它在类型别名、对象类型、函数与 Class 中的使用方式。 一、泛型的核…

19.备忘录模式:思考与解读

原文地址:备忘录模式:思考与解读 更多内容请关注:深入思考与解读设计模式 引言 在软件开发中,尤其是当对象的状态会经历多个变化时,你是否遇到过一个问题:如何保存对象的某一时刻的状态,以便在未来的某个…

【运营商查询】批量手机号码归属地和手机运营商高速查询分类,按省份城市,按运营商移动联通电信快速分类导出Excel表格,基于WPF的实现方案

WPF手机号码归属地批量查询与分类导出方案 应用场景 ​​市场营销​​:企业根据手机号码归属地进行精准营销,按城市或省份分类制定针对性推广策略​​客户管理​​:快速对客户手机号码进行归属地分类,便于后续客户关系管理​​数…

MySQL之函数

文章目录 函数字符串函数常见函数举例说明具体场景 数值函数常见函数举例说明具体场景 日期函数常见函数举例说明具体场景 流程函数常见函数举例说明具体场景 函数 函数 是指一段可以直接被另一段程序调用的程序或代码。 也就意味着,这一段程序或代码在MySQL中已经…

html,js获取扫码设备的输入内容

<script type"text/javascript"><!-- window.onload function () {// 获取扫描的二维码内容 var code ""; var lastTime, nextTime; var lastCode, nextCode; document.onkeypress function (e) { nextCode e.which; ne…

Nginx 配置 HTTPS 与 WSS 完整指南(最新推荐)

Nginx 配置 HTTPS 与 WSS 完整指南 一、准备工作 获取 SSL 证书 从可信机构&#xff08;如 Let’s Encrypt&#xff09;申请证书获得以下文件&#xff1a; 域名证书&#xff1a;domain.crt私钥文件&#xff1a;domain.key中间证书链&#xff1a;chain.crt 推荐合并证书链&…

选择合适的Azure数据库监控工具

Azure云为组织提供了众多服务&#xff0c;使其能够无缝运行应用程序、Web服务和服务器部署&#xff0c;其中包括云端数据库部署。Azure数据库能够与云应用程序实现无缝集成&#xff0c;具备可靠、易扩展和易管理的特性&#xff0c;不仅能提升数据库可用性与性能&#xff0c;同时…

CSS 文字样式全解析:从基础排版到视觉层次设计

CSS 文字样式目录 一、字体家族&#xff08;font-family&#xff09; 二、字体大小&#xff08;font-size&#xff09; 三、字体粗细&#xff08;font-weight&#xff09; 四、字体样式&#xff08;font-style&#xff09; 五、文本转换&#xff08;text-transform&#xf…

电子电气架构 --- 细化造车阶段流程

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…

谈谈Oracle BUFFER CACHE的命中率

BUFFER CACHE的命中率已成为一个老生常谈的话题&#xff0c;在数据库等待事件出现之前&#xff0c;DBA进行数据库系统级优化时&#xff0c;往往会首先观察BUFFER CACHE的命中率。命中率高就意味着数据库运行正常&#xff0c;很多Oracle官方提供的巡检脚本都将BUFFER CACHE的命中…

云渲染技术解析与渲酷平台深度测评:如何实现高效3D创作?

一、云渲染技术核心原理 1.1 分布式计算架构 云渲染的本质是通过多节点并行计算实现效率突破。以动画渲染为例&#xff0c;一个30秒的动画通常包含720帧&#xff08;按24帧/秒计算&#xff09;&#xff0c;传统单机需要连续处理所有帧&#xff0c;而云渲染可将任务拆解为720个…

JavaScript-DOM-02

自定义属性&#xff1a; ​ <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

Kind方式部署k8s单节点集群并创建nginx服务对外访问

资源要求 请准备好doker环境&#xff0c;尽量用比较新的版本。我的docker环境如下 docker 环境&#xff1a; Docker version 20.10.21, build 20.10.21-0ubuntu1~18.04.3 安装kind kind表现上就是一个二进制程序&#xff0c;下载对应版本并增加执行权限即可&#xff1a; cu…

MySQL备份恢复:数据安全的终极指南

引言 各位数据库爱好者们好&#xff01;今天我们要深入探讨MySQL数据库的"生命保险"——备份与恢复策略 &#x1f6e1;️。在数据即资产的时代&#xff0c;任何数据丢失都可能造成灾难性后果。本教程将带你全面掌握从逻辑备份到物理备份&#xff0c;从二进制日志恢复…

id分页遍历数据漏行问题

令入参id为0 while(true){ select * from table where id>#{id} order by id asc limit 100; 取结果集中最大id作为下次查询的入参 其他操作 } 这个算法一般没问题&#xff0c;但在主从数据系统中&#xff0c;主库写&#xff0c;查询从库遍历数据时&#xff0c;出现了…

OpenCV级联分类器

概念 OpenCV 级联分类器是一种基于 Haar 特征、AdaBoost 算法和级联结构的目标检测方法&#xff0c;通过多阶段筛选快速排除非目标区域&#xff0c;实现高效实时检测&#xff08;如人脸、行人等&#xff09;。 加载级联分类器 // 加载级联分类器CascadeClassifier cascade;// …

C++ inline 内联函数

一、定义与设计初衷 inline 函数是 C 中通过 减少函数调用开销 优化程序效率的机制。其核心设计初衷是 取代 C 语言中宏定义&#xff08;#define&#xff09;&#xff0c;同时解决宏的以下缺陷&#xff1a; 类型安全问题&#xff1a;宏仅进行文本替换&#xff0c;无法进行参数…

uniapp-商城-64-后台 商品列表(商品修改---页面跳转,深浅copy应用,递归调用等)

完成了商品的添加和展示&#xff0c;下面的文字将继续进行商品页面的处理&#xff0c;主要为商品信息的修改的页面以及后天逻辑的处理。 本文主要介绍了商品信息修改页面的实现过程。首先&#xff0c;页面布局包括编辑和删除功能&#xff0c;未来还可添加上架和下架按钮。通过c…

digitalworld.local: VENGEANCE靶场

1&#xff0c;将两台虚拟机网络连接都改为NAT模式 2&#xff0c;攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.182&#xff0c;靶场IP192.168.23.3 3&#xff0c;对靶机进行端口服务探测 nmap -sV -T4 -p- -A 192.168.23.3 端口号 协…

微店平台店铺商品接口开发指南

微店API获取店铺所有商品实现方案 以下是使用微店开放平台API获取店铺所有商品的完整实现代码&#xff0c;包含请求封装、分页处理和错误处理机制。 点击获取key和secret from weidian_api import WeidianAPI # 配置你的微店应用凭证 APP_KEY "your_app_key" APP_…