本文作者:张瑞远,现主要从事电信级IT系统及数据库的规划设计、架构设计、运维实施、运维服务、故障处理、性能优化等工作,曾经从事银行、证券数仓设计、开发、优化类工作,持有Orale OCM,MySQL OCP及国产代表数据库认证。 获得包括 OceanBase OBCE、Oracle OCP 11g 等专业技能与认证。

前言:

了解数据库优化技巧的朋友应当知道,在Oracle数据库中,处理大表的更新或删除时,常常借助rowid切片,这一方法能有效减少undo,支持并行执行,降低IO负载,从而提升效率。

同样地,OceanBase也支持rowid切片,相关知识的详细介绍可参阅以下OceanBase知识库链接。

https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000209970?back=kb

这个方法使用过程中也要注意一些事情,可以先了解下ob的rowid是怎么生成的,严军老师的博客有比较详细的介绍,链接如下

Oracle 和 OceanBase中ROWID的区别

1731983977

所以如果更新字段中包括主键的话,通过rowid切片然后去批量更新的话,可能会产生冲突和部分切片的数据变化。

案例:

注意事项

1.更新列尽量不包括主键

2.切片大小尽量在2W-10W左右

3.更新尽量减少涉及分区(如果并发高涉及分区多,3.x很容易触发4023的报错,虽然是等待clog滑动窗口不是直接报错,但是效率会变的很差)

4.对于无法确定分区拆分的场景,减少并发(限制并发和每个切片的数据量也可以避免4013内存不足的发生)

5.表上的触发器尽量关闭,复杂和大量的触发器对于效率影响很大

比如我们需要更新USERCS.TABLECS 的col1字段,并且确定该表无其他业务操作,而且数据基本分布在666,777的分区里,那么shell脚本如下

#!/bin/sh
export ip_a=xxx.xx.xx.xx            --数据库ip
export tenant_a=obcstenant          --数据库业务租户
export colony_a=obcscluster         --数据库集群
export colony_pw='xadsadqwdasf'     --数据库密码
echo "#### BEGIN ALTER PASSWD AND TBALEMODE  `date +%Y%m%d%H%M%S`####"
obclient -h${ip_a} -P2883 -usys@${tenant_a}#${colony_a} -p${colony_pw} -c <<EOF 
alter user USERCS identified by USERCS123;                            --因为测试环境为了避免影响以及方便添加了修改密码的操作
EOF
echo "#### END ALTER PASSWD AND TBALEMODE  `date +%Y%m%d%H%M%S`####"echo "#### CREATE ABOUT TRIGGER SQLFILE `date +%Y%m%d%H%M%S`####"     --关闭和打开触发器的sql语句
> /usr/syncscript/custcs/disable_trigger.sql
> /usr/syncscript/custcs/enable_trigger.sql
obclient -h${ip_a} -P2883 -usys@${tenant_a}#${colony_a} -p${colony_pw} -c  -N <<!|tee >> /usr/syncscript/custcs/disable_trigger.sql
select  'alter trigger  '||OWNER||'.'||TRIGGER_NAME||' DISABLE;'  from  dba_triggers where TABLE_OWNER='USERCS' and TABLE_NAME in ('TABLECS')  and  STATUS='ENABLED';
!
obclient -h${ip_a} -P2883 -usys@${tenant_a}#${colony_a} -p${colony_pw} -c  -N <<!|tee >> /usr/syncscript/custcs/enable_trigger.sql
select  'alter trigger  '||OWNER||'.'||TRIGGER_NAME||' enable;'  from  dba_triggers where TABLE_OWNER='USERCS' and TABLE_NAME in ('TABLECS')  and  STATUS='ENABLED';
!
echo "#### END ABOUT TRIGGER SQLFILE `date +%Y%m%d%H%M%S`####"echo "#### BEGIN DISABLE TRIGGER `date +%Y%m%d%H%M%S`####"               --关闭触发器
obclient -h${ip_a} -P2883 -usys@${tenant_a}#${colony_a} -p${colony_pw} -c <<EOF 
source /usr/syncscript/custcs/disable_trigger.sql
EOF
echo "#### END DISABLE TRIGGER `date +%Y%m%d%H%M%S`####"echo "#### BEGIN CREATE TABLECS SQLFILE `date +%Y%m%d%H%M%S`####"         --生成USERCS.TABLECS根据rowid切片的sql
export des_table=USERCS.TABLECS 
export des_file=TABLECS
export des_count=1000                                                     --整个表切成1000份, 可以先count一下表看下数据量,确保每个分片不会太大不会太小,group分区键看下数据分布
export des_sh_name=subscssss                                              --生成批量脚本的前缀名称
>/usr/syncscript/custcs/${des_file}.sql
obclient -h${ip_a} -P2883 -uUSERCS@${tenant_a}#${colony_a} -p'USERCS123' -c  -N <<!|tee >> /usr/syncscript/custcs/${des_file}.sql     --生成USERCS.TABLECS根据rowid切片的sql
with a as
(select  str as ob_id,rownum rn from  (select ob_rowid,decode(mod(rownum,trunc((select count(*) from ${des_table} where partition_id in (666,777) )/${des_count})),0,''||rowid,'') str,rownum seq from (select  rowid ob_rowid from ${des_table} where partition_id in (666,777) order by 1 )) where str is not null order by seq)
select  'update  USERCS.TABLECS t  set COL1=''xxxxxxxxxxx''  where partition_id in (666,777) and rowid '||case when  rc=0 then '< '''||OB_ID1||'''; commit;'  when rc is null then '>= '''||OB_ID1||'''; commit;' else '>= '''||OB_ID1||''' and rowid<'''||ob_id2||'''; commit;' end as  sql1from  (
select ob_id ob_id1,'' ob_id2,rn,0 as rc  from  a where rn=1 union all
select a1.ob_id ob_id1,a2.ob_id,a1.rn rownum1,a2.rn rownum2   from  a a1 left join a a2 on a1.rn=a2.rn-1) order by rn;
!export cnt3=`cat /usr/syncscript/custcs/${des_file}.sql|wc -l`    --统计生成的sql数量
export des_ma=`expr $cnt3 / 13`                                   --拆分为13份脚本echo "#### BEGIN  NO666,777 TABLECS DATA  `date +%Y%m%d%H%M%S`####"       --先确认了非666,777分区的数据很少,可以单独更新
obclient -h${ip_a} -P2883 -uUSERCS@${tenant_a}#${colony_a} -p'USERCS123' -c <<EOF 
update  USERCS.TABLECS t  set COL1=''xxxxxxxxxxx'' where  partition_id not  in (666,777);
EOF
echo "#### END  NO666,777 TABLECS DATA  `date +%Y%m%d%H%M%S`####"split -d -l ${des_ma} ${des_file}.sql   ${des_sh_name} &&ls|grep ${des_sh_name}|xargs -i mv {} {}.sh        --拆分rowid切分的sql文件成13个脚本
ls|grep ${des_sh_name}|xargs -i sed -i "1iobclient -h${ip_a} -P2883 -uUSERCS@${tenant_a}#${colony_a} -p'USERCS123' -c <<EOF " {}
ls|grep ${des_sh_name}|xargs -i sed -i "1i#!/bin/sh"  {}
find . -name  "${des_sh_name}*"|xargs -i sed  -i '$a\EOF'  {}
find . -name  "${des_sh_name}*"|xargs -i sed  -i '$a\echo "####{} END `date +%Y%m%d%H%M%S`"'  {}
echo "#### END CREATE SQLFILE `date +%Y%m%d%H%M%S`####"
echo "#### BEGIN RUN DESEN `date +%Y%m%d%H%M%S`####"
export cn=`ls|grep ${des_sh_name}|wc -l`                            --并发度控制,因为这里拆分的脚本只有13个,所以有多少脚本设置的多少并发,如果单分区大表或者无法按照分区拆分的大表可以多分一些切片,多分些脚本,cn并发写成固定的值比如5
ls|grep ${des_sh_name}|xargs -i -P ${cn} sh {} &                    --并发执行生成的这些脚本
wait
rm -rf /usr/syncscript/custcs/${des_sh_name}*
echo "#### END RUN TABLECS DESEN `date +%Y%m%d%H%M%S`####"echo "#### BEGIN ENABLE TRIGGER `date +%Y%m%d%H%M%S`####"           --打开触发器   
obclient -h${ip_a} -P2883 -usys@${tenant_a}#${colony_a} -p${colony_pw} -c <<EOF 
source /usr/syncscript/custcs/enable_trigger.sql
EOF
echo "#### END ENABLE TRIGGER `date +%Y%m%d%H%M%S`####"

上面写了如果单分区大表或者无法按照分区拆分的大表可以多分一些切片,多分些脚本,cn并发写成固定的值比如5,案例如下

echo "#### BEGIN CREATE TABLECS2 SQLFILE `date +%Y%m%d%H%M%S`####"
export des_table=USERCS1.TABLECS2 
export des_file=TABLECS2
export des_count=2000                             --按照rowid切分为2000份
export des_sh_name=tbsfcssss
>/usr/syncscript/custcs/${des_file}.sql
obclient -h${ip_a} -P2883 -uUSERCS1@${tenant_a}#${colony_a} -p'USERCS1123' -c  -N <<!|tee >> /usr/syncscript/custcs/${des_file}.sql
with a as
(select  str as ob_id,rownum rn from  (select ob_rowid,decode(mod(rownum,trunc((select count(*) from ${des_table} )/${des_count})),0,''||rowid,'') str,rownum seq from (select  rowid ob_rowid from ${des_table}  order by 1 )) where str is not null order by seq)
select  'update  USERCS1.TABLECS2 t  set  COL2=''ASDASD'' where rowid '||case when  rc=0 then '< '''||OB_ID1||'''; commit;'  when rc is null then '>= '''||OB_ID1||'''; commit;' else '>= '''||OB_ID1||''' and rowid<'''||ob_id2||'''; commit;' end as  sql1from  (
select ob_id ob_id1,'' ob_id2,rn,0 as rc  from  a where rn=1 union all
select a1.ob_id ob_id1,a2.ob_id,a1.rn rownum1,a2.rn rownum2   from  a a1 left join a a2 on a1.rn=a2.rn-1) order by rn;
!export cnt3=`cat /usr/syncscript/custcs/${des_file}.sql|wc -l`
export des_ma=`expr $cnt3 / 200`                            -- 切分成200个脚本          split -d -l ${des_ma} ${des_file}.sql   ${des_sh_name} &&ls|grep ${des_sh_name}|xargs -i mv {} {}.sh 
ls|grep ${des_sh_name}|xargs -i sed -i "1iobclient -h${ip_a} -P2883 -uUSERCS1@${tenant_a}#${colony_a} -p'USERCS1123' -c <<EOF " {}
ls|grep ${des_sh_name}|xargs -i sed -i "1i#!/bin/sh"  {}
find . -name  "${des_sh_name}*"|xargs -i sed  -i '$a\EOF'  {}
find . -name  "${des_sh_name}*"|xargs -i sed  -i '$a\echo "####{} END `date +%Y%m%d%H%M%S`"'  {}
echo "#### END CREATE SQLFILE `date +%Y%m%d%H%M%S`####"
echo "#### BEGIN RUN DESEN `date +%Y%m%d%H%M%S`####"
export cn=5                                                 --按照并发5去执行切分后的脚本
ls|grep ${des_sh_name}|xargs -i -P ${cn} sh {} &
wait
rm -rf /usr/syncscript/custcs/${des_sh_name}*
echo "#### END RUN TABLECS2 DESEN `date +%Y%m%d%H%M%S`####"

总结:

通过合理利用rowid切片技术,可以显著提高在OceanBase中对大表进行更新或删除操作的效率。希望本文能帮助大家在实际工作中更好地优化数据库操作,提升系统性能。

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

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

相关文章

【从0开始学习Java | 第4篇】类和对象

文章目录&#x1f44f;类和对象的概念什么是类&#xff1f;什么是对象&#xff1f;&#x1f95d;构造方法如何创建一个对象&#xff1f;&#x1f95d;对象内存布局完整应用 - 编写一个类&#xff1a;人&#xff0c;其具备年龄、性别、姓名等基础属性&#xff0c;并实例化一个人…

Synopsys:默认报告精度(report_default_significant_digits变量)

相关阅读 Synopsyshttps://blog.csdn.net/weixin_45791458/category_12812219.html?spm1001.2014.3001.5482 在使用report_timing之类的报告命令时&#xff0c;可以使用-significant_digits选项指定报告的精度&#xff0c;在不使用该选项的情况下&#xff0c;命令使用由repor…

2025年蓝桥杯青少图形化编程国考真题——摆放玩具

编程实现摆放玩具。&#xff08;角色非源素材&#xff09;摆放规则&#xff1a;在方格中摆放玩具&#xff0c;每个方格只能摆放一个&#xff0c;并且如果某个方格中已经摆放了玩具&#xff0c;那么与之上、下、左、右相邻的四个方格中无法再摆放同种玩具。具体要求1&#xff09…

Android 应用的安装流程

安装流程总览&#xff1a; 用户触发安装->系统验证APK的合法性->解析APK元数据->检查权限和存储空间->复制APK到目标位置->生成应用私有数据->注册组件到系统->安装完成 关键步骤&#xff1a; 1.用户触发安装&#xff1a;a.通过应用商店b.通过adb命令c.通…

基于 Amazon Bedrock 与 Anthropic Claude 3 智能文档处理方案:从扫描件提取到数据入库全流程实践

基于 Amazon Bedrock 与 Anthropic Claude 3 智能文档处理方案&#xff1a;从扫描件提取到数据入库全流程实践 文章目录基于 Amazon Bedrock 与 Anthropic Claude 3 智能文档处理方案&#xff1a;从扫描件提取到数据入库全流程实践方案架构前提准备&#xff1a;亚马逊云科技注册…

深入浅出设计模式——创建型模式之单例模式 Singleton

文章目录“天上天下&#xff0c;唯我独尊”——单例模式单例模式简介单例模式结构饿汉式懒汉式客户端示例运行结果单例模式总结构建型模式 Creational Patterns 小结 Summary代码仓库“天上天下&#xff0c;唯我独尊”——单例模式 你能在电脑上调出两个Windows任务管理器吗&a…

静电释放检测漏报率↓85%!陌讯多模态融合算法在电子厂ESD防护实战解析

​摘要​​ 基于边缘计算的静电释放(ESD)视觉检测方案&#xff0c;通过多模态融合技术显著提升复杂场景鲁棒性。实测显示&#xff1a;在电子元件装配线上&#xff0c;ESD事件检测mAP0.5达89.1%&#xff0c;较基线模型提升28.3%。一、行业痛点&#xff1a;ESD检测的隐形危机根据…

RAL-2025 | “藏宝图”驱动的具身导航!HAM-Nav:基于手绘地图引导的机器人导航

作者&#xff1a;Aaron Hao Tan, Angus Fung, Haitong Wang, Goldie Nejat单位&#xff1a;多伦多大学机械与工业工程系论文标题&#xff1a;Mobile Robot Navigation Using Hand-Drawn Maps: A Vision Language Model Approach出版信息&#xff1a;IEEE ROBOTICS ANDAUTOMATI…

Vue.js 与后端技术结合开发指南

Vue.js 作为现代化的前端框架&#xff0c;可以与多种后端技术完美结合&#xff0c;构建全栈应用。下面我将详细介绍 Vue 可以与哪些后端技术结合开发&#xff0c;并提供可视化示例。Vue 可结合的后端技术概览主流组合方案对比后端技术适合场景优点缺点学习曲线Node.js全栈JavaS…

逻辑回归在银行贷款审批中的应用:参数选择与实践

目录 一、数据背景与预处理 1.数据前五行 2.数据预处理步骤 二、逻辑回归的正则化参数选择 1.交叉验证选择最优C 2.为什么选择召回率作为评估指标&#xff1f; 三、参数选择的核心结论 四、后续优化方向 在银行贷款审批场景中&#xff0c;准确判断贷款人是否符合贷款条…

数据结构前篇 - 深入解析数据结构之复杂度

目录一、数据结构前言1.1 数据结构1.2 算法二、算法效率2.1 复杂度的概念三、时间复杂度3.1 大O的渐进表示法3.2 时间复杂度计算示例3.2.1 示例13.2.2 示例23.2.3 示例33.2.4 示例43.2.5 示例53.2.6 示例63.2.7 示例7四、空间复杂度4.1 空间复杂度计算示例4.1.1 示例14.1.2 示例…

Master Prompt:AI时代的万能协作引擎

1. Master Prompt&#xff1a;为什么它正在重塑AI协作范式大模型落地的最大痛点不是技术本身&#xff0c;而是人机协作的断裂。当企业采购了昂贵的AI系统&#xff0c;却发现输出内容反复偏离预期&#xff0c;团队成员抱怨“AI总听不懂我要什么”&#xff0c;这种场景每天在无数…

《Kubernetes部署篇:基于Kylin V10+ARM架构CPU使用containerd部署K8S 1.33.3容器板集群(一主多从)》

总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:企业级K8s集群运维实战 一、架构图 如下图所示: 二、环境信息 基于x86_64+aarch64架构使用containerd部署K8S 1.33.3集群资源合集(一主多从) 2、部署规划 主机名 K8S版本 系统版本 CPU架构 内核版…

一次性接收大量上传图片,后端优化方式

文章目录1. 分块接收与流式处理2. 异步处理3. 内存映射与临时文件4. 数据库优化5. 缓存策略6. 压缩与格式优化7. 限流与并发控制8. 分布式存储9. 响应优化10. 监控与错误处理11. 数据库连接池优化1. 分块接收与流式处理 使用流式处理避免将所有图片加载到内存中&#xff1a; …

二分查找(基础)

竞赛中心 - 蓝桥云课 #include <iostream> #include<bits/stdc.h> using namespace std; #define int long long int N; struct NO {int A,B; }a[10001]; bool ok(int V) {for (int i 0; i < N; i){if (a[i].A / V ! a[i].B){return false;}}return true; } …

流式编程学习思路

流式编程学习思路 作为Java初级工程师,想要掌握流式编程并向高级工程师进阶,需要从基础到进阶逐步掌握,结合实战场景深化理解。以下是为你量身定制的学习清单和思路: 一、基础阶段:吃透 Java Stream 核心API 1. 掌握 Stream 的基本概念 什么是 Stream:理解它与集合(Co…

13-14linux三剑客grep,sed,awk

目录 三剑客支持扩展正则写法 grep命令 sed命令 sed指定行查找&#xff1a; sed模糊过滤文件内容 sed之删除&#xff1a; sed之替换&#xff1a; sed追加插入替换&#xff1a; sed后向引用&#xff1a; awk命令 awk按照行查找 awk模糊过滤文件内容 awk取列 awk指…

损失函数和调度器相关类代码回顾理解 |nn.CrossEntropyLoss\CosineAnnealingLR

目录 nn.CrossEntropyLoss CosineAnnealingLR nn.CrossEntropyLoss loss_func nn.CrossEntropyLoss(reduction"sum") 定义nn.CrossEntropyLoss交叉熵损失函数&#xff0c;reduction参数设置为"sum"&#xff0c;表示将所有样本的损失相加。reduction 参…

中国不同类型竹林分布数据

中国竹林分布的主要特点简介&#xff1a;总体分布格局&#xff1a;核心区域&#xff1a; 主要分布在长江流域及以南的广大亚热带和热带地区。北界&#xff1a; 大致以黄河流域为北界&#xff0c;但天然成片竹林在秦岭-淮河一线以南才比较普遍。人工引种或特殊小环境下&#xff…

Sqlserver备份恢复指南-完整备份恢复

博主会用简单清晰的方式&#xff0c;带你系统学习使用T-SQL命令行的方式 给SQL Server 做备份与恢复。我们按照从零开始、逐步深入的路线来讲解&#xff01; 完整备份恢复-差异增量备份恢复-事务日志备份恢复 &#x1f538; SQL Server 备份类型&#xff1a;类型说明完整备份&a…