如何利用 rowid 在OceanBase 中處理大表時提效

本文作者:張瑞遠,現主要從事電信級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…