在每天的AWR报告巡检中发现一性能SQL情况,发现 db file sequential read等待事件消耗在User I/O,再看SQL有个UPDATE语句16.81%的IO消耗,然后再查看这张表的数据达到了9亿+,大表还自关联,头痛来袭。
update BUFFER_TMP
set STATUS='Y' , LAST_UPADTE_TIME=sysdate
where STATUS='N'
and ID='2024091309581000101'
and TRAN_TIME>=sysdate-7
and TRAN_SEQ in (select TRAN_SEQ from BUFFER_TMP
where ROWNUM<5001 and STATUS='N'
and ID='2024091309581000101' );
update BUFFER_TMP
set STATUS='Y' , LAST_UPADTE_TIME=sysdate
where STATUS='N'
and ID='2024091309581000101'
and TRAN_TIME>=sysdate-7
and ROWNUM<5001;
create table BUFFER_TMP
(......略)
partition by range (TRAN_TIME) -- 分区字段
subpartition by list (STATUS) -- 子分区字段
-- 表数据库:9亿+
SQL> select count(*) from BUFFER_TMP ;
COUNT(*)
----------
905107731
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
System altered.
逻辑读:18986/9348 = 2.03 物理读:10119/936 = 10.81
COST:4502K/2576 = 1747.67 执行时间:00:00:02.29 下降至:00:00:00.45
解读:从IO表现来分析,逻辑读提高2+倍、物理读提高10+倍。Cost提升了1747+倍,执行时间提高近原来的SQL对表进行了2次全表扫,变装后仅全表扫了1次。从这3点来看变装后的SQL要比原SQL更优。使用过程完成对固定数据的更新,对比效率
-- 需要更新的数据:40w+
SQL> select count(*) from BUFFER_TMP where STATUS= 'N' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd');
COUNT(*)
----------
462896
SQL> SET SERVEROUTPUT ON;
SQL> -- 刷新内存
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
Elapsed: 00:00:00.11
SQL> alter system flush buffer_cache;
System altered.
Elapsed: 00:00:00.10
SQL> -- 变装前
SQL> DECLARE
2 var_num int;
3 i int ;
4 BEGIN
5 select count(*) into var_num from BUFFER_TMP where STATUS = 'N' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd');
6 for i in 1..trunc(var_num/5000)+1 loop
7 update BUFFER_TMP
8 set STATUS='Y' , LAST_UPADTE_TIME=sysdate
9 where STATUS='N'
10 and ID='2024091309581000101'
11 and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd')
12 and TRAN_SEQ in (select TRAN_SEQ from pay.BUFFER_TMP
13 where ROWNUM<5001 and STATUS='N'
14 and ID='2024091309581000101' );
15 commit;
16 end loop;
17 commit;
18 dbms_output.put_line('完成循环:'||'='||to_char(mod(var_num,5000)+1) || '次');
19 EXCEPTION
20 WHEN OTHERS THEN
21 dbms_output.put_line('失败');
22 END;
23 /
完成循环:=93次
PL/SQL procedure successfully completed.
Elapsed: 00:01:37.72
-- 数据已全部更新:STATUS = 'N' 为0
SQL> select count(*) from BUFFER_TMP where STATUS = 'N' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd');
COUNT(*)
----------
0
Elapsed: 00:00:00.27
SQL> update BUFFER_TMP set STATUS='N' where STATUS= 'Y' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd');
462896 rows updated.
Elapsed: 00:00:12.35
SQL> commit;
Commit complete.
Elapsed: 00:00:00.05
SQL> SET SERVEROUTPUT ON;
SQL> -- 刷新内存
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
Elapsed: 00:00:00.17
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
System altered.
Elapsed: 00:00:00.10
SQL> -- 变装后
SQL> DECLARE
2 var_num int;
3 i int ;
4 BEGIN
5 select count(*) into var_num from BUFFER_TMP where STATUS = 'N' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd');
6 for i in 1..trunc(var_num/5000)+1 loop
7 update BUFFER_TMP
8 set STATUS='Y' , LAST_UPADTE_TIME=sysdate
9 where STATUS='N' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd') AND ROWNUM<5001;
10 commit;
11 end loop;
12 commit;
13 dbms_output.put_line('完成循环:'||'='||to_char(mod(var_num,5000)+1) || '次');
14 EXCEPTION
15 WHEN OTHERS THEN
16 dbms_output.put_line('失败');
17 END;
18 /
完成循环:=93次
PL/SQL procedure successfully completed.
Elapsed: 00:01:16.80
-- 数据已全部更新:STATUS = 'N' 为0
SQL> select count(*) from pay.BUFFER_TMP where STATUS = 'N' and ID='2024091309581000101' and TRAN_TIME>=to_date('2024-09-01','yyyy-mm-dd');
COUNT(*)
----------
0
Elapsed: 00:00:00.30
select count(*) from BUFFER_TMP t
where STATUS='N'
and ID='2024091309581000101'
and TRAN_TIME>=to_TIMESTAMP('2024-09-01','yyyy-mm-dd')
and ROWNUM<5001;
SQL> create index idx_buffer_tran_time_id on buffer_tmp (tran_time,id,status) local;
Index created.
Elapsed: 00:34:07.45
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。