Oracle SQL性能优化案例----数据入库和更新任务

Oracle SQL性能优化案例----数据入库和更新任务

一、需求(每月定时一次)

1、订购关系入库和更新任务

复制代码
1)原订购关系表数据备份
2)本月订购关系数据入库(通过sqlldr脚本,大约10-15G,1-10亿条数据)
3)对入库的订购关系表进行更新

2、用户状态入库和更新任务

复制代码
1)原用户状态表数据备份
2)本月用户状态数据入库(通过sqlldr脚本,大约10-15G,1-10亿条数据)
3)对入库的用户状态表进行更新

备注:

1)任务期间,表无需对外访问,可以独占资源

2)订购关系表和用户状态表,表上都有索引

二、完成任务的步骤

1、订购关系入库和更新任务
复制代码
1)清理原先的备份表(任务每月一次,即清理上个月的备份表数据),语句如下
truncate table user_order_bak;
-- user_order_bak表为备份表

2)原订购关系表数据备份
insert into user_order_bak t
select  * from user_order a;
commit;

3)清理原订购关系表
truncate table user_order;

4)本月的订购关系数据入库
insert_order.ctl
LOAD DATA
INFILE 'xxxxxxxxx'
append into TABLE user_order 
FIELDS TERMINATED BY ","
(
A_XXXX,
B_XXXX,
C_XXXX,
D_XXXX,
E_XXXX,
F_XXXX,
G_XXXX  date 'yyyy-mm-dd hh24:mi:ss',
H_XXXX,
I_XXXX,
J_XXXX,
K_XXXX
)

sqlldr 用户名/密码 control=insert_order.ctl log=insert_order.log


5)对入库的订购关系表进行更新,划分归属地(以归属表的某列条件来更新该表)
DECLARE
BEGIN
     FOR GET_REGOIN IN( SELECT C1,REGION_CODE FROM  TAB_NUMBER_XXXX)
     LOOP
          UPDATE user_order SET E_XXXX=GET_REGOIN.REGION_CODE
          WHERE  C_XXXX LIKE GET_REGOIN.C1||'%';
         COMMIT;
     END LOOP;
     COMMIT;
END;

6)表重新收集统计信息
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>user,TABNAME=>'user_order',ESTIMATE_PERCENT=>1,METHOD_OPT=>'FOR ALL COLUMNS SIZE 1',NO_INVALIDATE=>FALSE,CASCADE=>TRUE,DEGREE => 10);
END; 
/
2、用户状态入库和更新任务

与"订购关系入库和更新任务"基本相似,不再重复赘述

三、重点待优化的步骤

"订购关系入库"步骤,如果不做优化,需要15个小时以上

"对入库的订购关系表进行更新,划分归属地"步骤,需要15个小时以上

四、具体优化的步骤

以"订购关系入库和更新任务"为例,另一个基本相似,不重复赘述

1、"清理原先的备份表、原订购关系表数据备份",这两个步骤,优化方法如下

复制代码
1)直接删除原先的备份表
drop table user_order_bak;
2)ctas+nologging+parallel方式备份原订购关系表数据
create table user_order_bak nologging parallel 4
as
select /*+ parallel(a 4) */ * from user_order a;

alter table user_order_bak logging noparallel;

结论:对于大表而言,ctas+nologging+parallel方式,速度比 insert+select方式快很多

2、"本月订购关系数据入库"步骤,优化方法如下

复制代码
1)删除表上索引
drop INDEX IDX_user_order_C_XXXX ;
drop index IDX_user_order_A_XXXX 
drop index IDX_user_order_D_XXXX 
drop index IDX_user_order_F_XXXX 
drop index IDX_user_order_G_XXXX 

2)sqlldr方式入库,添加如下选项,提高sqlldr加载速度
direct=y parallel=true bindsize=100000000 readsize=20971520 date_cache=10000000 

备注:索引先不创建,后续优化步骤需要

结论:

1)对于大批量数据导入或者插入,先删除表上的索引,数据导入完成后,再重建索引,速度会快几个量级;

2)表数据插入/导入期间,如果表中有索引,DML期间需要维护索引结构,涉及到索引的redo日志,索引数据的有序组织,索引的叶子块分配、分裂等等,随着数据量的增加,插入/导入的速度会越来越慢!!

3、"对入库的订购关系表进行更新"步骤,优化方法如下

复制代码
1)将新入库的订单表重命名
alter table user_order rename to user_order_TMPBAK;

2)CTAS+NOLOGGING+PARALLEL方式重建新的订单表,并且以order by C_XXXX的方式组织表中的数据,这一步非常重要
create table user_order parallel 10 nologging
as
select /*+ parallel(a 10) */ *
  from user_order_TMPBAK a
 order by C_XXXX;
--  order by C_XXXX顺序组织数据

alter table user_order noparallel logging;

3)验证数据量,无误后,删除TMPBAK表
select /*+ parallel(t 10) */ count(*) from  user_order t;
select /*+ parallel(t 10) */ count(*) from  user_order_DHBAK t;
DROP TABLE user_order_TMPBAK;

4)重建索引
drop INDEX IDX_user_order_C_XXXX ;
drop index IDX_user_order_A_XXXX 
drop index IDX_user_order_D_XXXX 
drop index IDX_user_order_F_XXXX 
drop index IDX_user_order_G_XXXX 
CREATE INDEX IDX_user_order_C_XXXX ON user_order(A_XXXX)  parallel 10 nologging;
CREATE INDEX IDX_user_order_C_XXXX ON user_order(C_XXXX)  parallel 10 nologging;
CREATE INDEX IDX_user_order_C_XXXX ON user_order(D_XXXX)  parallel 10 nologging;
CREATE INDEX IDX_user_order_C_XXXX ON user_order(F_XXXX)  parallel 10 nologging;
CREATE INDEX IDX_user_order_C_XXXX ON user_order(G_XXXX)  parallel 10 nologging;

alter index  IDX_user_order_A_XXXX noparallel logging;
alter index  IDX_user_order_C_XXXX noparallel logging;
alter index  IDX_user_order_D_XXXX noparallel logging;
alter index  IDX_user_order_F_XXXX noparallel logging;
alter index  IDX_user_order_G_XXXX noparallel logging;

5)收集统计信息,为后续更新作铺垫
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'CBOSS',TABNAME=>'user_order',ESTIMATE_PERCENT=>1,METHOD_OPT=>'FOR ALL COLUMNS SIZE 1',NO_INVALIDATE=>FALSE,CASCADE=>TRUE,DEGREE => 10);
END; 
/

6)对入库的订购关系表进行更新,划分归属地(以归属表的某列条件来更新该表)
DECLARE
BEGIN
     FOR GET_REGOIN IN( SELECT C1,REGION_CODE FROM  TAB_NUMBER_XXXX)
     LOOP
          UPDATE user_order SET E_XXXX=GET_REGOIN.REGION_CODE
          WHERE  C_XXXX LIKE GET_REGOIN.C1||'%';
         COMMIT;
     END LOOP;
     COMMIT;
END;  
/

结论:优化C_XXXX列索引的聚簇因子,使得C_XXXX的索引顺序和表中的数据存储顺序两者接近一致,对于使用C_XXXX LIKE 前缀的查询条件(同时更新改行),通过该条件返回的索引行,进行回表时,所需数据会集中在表中几个数据块中(索引列顺序和表存储顺序一致),这样会大大提升查询和更新速度

五、总结

经过整体优化后,整个入库和更新的每月定时任务,在3个小时内完成!

整个过程中,是否还有可以优化的地方呢?肯定还是有很多的,例如,是否可以考虑临时表?剩下的留给大家思考吧。

相关推荐
tryxr1 小时前
如何分析一个慢sql
数据库·sql·mysql·慢sql
泡海椒2 小时前
JQuickExcel 大文件排障与调优:从实际路径定位 OOM、临时盘和慢任务
开发语言·数据库·缓存·oracle·excel
达梦数据2 小时前
达梦数据复制软件DMDRS搭建部署示例:源数据库DM8到目标数据库Kingbase V8一对一数据同步
数据库·oracle
打工仔折腾 AI2 小时前
CentOS 7 单机部署 Elasticsearch 7.17.29:启动报错排查与 CRUD 验证
人工智能·后端·python·elasticsearch·性能优化·centos·jenkins
HEJOO92 小时前
iOS 性能优化全面详解
ios·性能优化·cocoa
烟雨归来3 小时前
Oracle备份NFS IO挂死引发PQ并行进程耗尽process
数据库·oracle
acd120093 小时前
PHP 8.1 下 Swoole 协程 PDO 偶尔出现 MySQL 连接丢失问题排查
数据库·oracle
cc5725026533 小时前
2027校招:大数据管理与应用转财务数字化,会计业务、SQL与BI学习路线
数据库·sql·学习
yunwei375 小时前
eBPF 实例教程:BPF Arena 零拷贝共享内存
linux·后端·性能优化