批量更新效能比較
目的:
1,批量更新幾種方案對比(undo,執行時間)
2,非分割槽表是否支援並行驗證
--環境
-----------------
硬體環境:
uatdb1:/oracle/app/oracle$prtconf
uatdb1:/oracle/app/oracle$ prtconf
System Model: IBM,9119-595
Machine Serial Number: 83F13CE
Processor Type: PowerPC_POWER5
Number Of Processors: 6
Processor Clock Speed: 1900 MHz
CPU Type: 64-bit
Kernel Type: 64-bit
LPAR Info: 21 uatdb1
Memory Size: 12288 MB
Good Memory Size: 12288 MB
Platform. Firmware level: Not Available
Firmware Version: IBM,SF240_358
Console Login: enable
Auto Restart: true
Full Core: false
OS版本:
uatdb1:/oracle/app/oracle$ uname -a
AIX uatdb1 3 5 00CF13CE4C00
Oracle 版本:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.3.0 - Productio
NLSRTL Version 10.2.0.3.0 - Production
SQL> show parameter target
pga_aggregate_target big integer 1G
sga_target big integer 8G
0.準備:
0.1 users_chnl_a為需要更新的目標表:
drop table users_chnl_a;
create table users_chnl_a
as
select * from users_chnl;
alter table users_chnl_a
add constraint PK_users_chnl_a primary key (USER_ID, CHNL);
begin
dbms_stats.gather_table_stats(ownname => user,tabname => 'USERS_CHNL_A',degree => 8,cascade => true);
end;
/
select table_name,num_rows from user_tables where table_name='USERS_CHNL_A';
TABLE_NAME NUM_ROWS
USERS_CHNL_A 22292951
0.2 更新參照表users_chnl_pwd:
create table users_chnl_pwd nologging
as
select user_id,chnl,password,login_name,lpad('1',32,'1') npassword
from users_chnl
where 1=2;
--rec_id 唯一序列號,FLAG 處理標記
alter table users_chnl_pwd add(rec_id integer,flag integer);
--需記錄該日期,在第三步使用
prompt 需記錄該日期,在第三步使用
select to_char(trunc(sysdate),'YYYYMMDD HH24MISS') "to_date" from dual;
alter session enable parallel dml;
insert /*+ parallel(t1 8) */ into users_chnl_pwd t1
select /*+ parallel(t2 8) */ user_id,chnl,password,login_name,lpad('1',32,'1') npassword,SEQ_users_chnl_recid.nextval,'0'
from users_chnl t2
where crt_date<=trunc(sysdate);
commit;
alter session disable parallel dml;
create unique index uidx_users_chnl_pwd on users_chnl_pwd(user_id,chnl) parallel 8;
create unique index uidx_users_chnl_pwd_recid on users_chnl_pwd(rec_id) parallel 8;
begin
dbms_stats.gather_table_stats(ownname => user,tabname => 'USERS_CHNL_PWD',degree => 8,cascade => true);
end;
/
select table_name,num_rows from user_tables where table_name='USERS_CHNL_PWD';
TABLE_NAME NUM_ROWS
USERS_CHNL_PWD 22334054
--1,方案1,直接更新:
create unique index uidx_users_chnl_npwd on users_chnl_pwd(user_id,chnl,npassword) parallel 8;
alter session enable parallel dml;
update /*+ parallel(u 8) */ (select /*+ parallel(uc 8) parallel(ucp 8) */
uc.password,
ucp.npassword
from users_chnl_a uc,users_chnl_pwd ucp
where uc.user_id=ucp.user_id
and uc.chnl=ucp.chnl
) u set u.password=npassword;
commit;
alter session disable parallel dml;
==>1800 seconds
--回滾段跟蹤:
SELECT sum(used_ublk)*8/1024,sum(used_urec)
FROM v$transaction
WHERE addr = ANY
(SELECT taddr
FROM v$session
WHERE saddr = ANY
(SELECT saddr FROM gv$px_session WHERE qcsid = 375));
2.639GB 22292959
---------執行計劃:
explain plan for
update /*+ parallel(u 8) */ (select /*+ parallel(uc 8) parallel(ucp 8) */
uc.password,
ucp.npassword
from users_chnl_a uc,users_chnl_pwd ucp
where uc.user_id=ucp.user_id
and uc.chnl=ucp.chnl
) u set u.password=npassword;
select * from table(dbms_xplan.display);
Plan hash value: 3364305002
---------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 21M| 1718M| | 28890 (1)| 00:05:47 | | | |
| 1 | PX COORDINATOR | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10004 | 21M| 1718M| | 28890 (1)| 00:05:47 | Q1,04 | P->S | QC (RAND) |
| 3 | INDEX MAINTENANCE | USERS_CHNL_A | | | | | | Q1,04 | PCWP | |
| 4 | PX RECEIVE | | 21M| 1718M| | 28890 (1)| 00:05:47 | Q1,04 | PCWP | |
| 5 | PX SEND RANGE | :TQ10003 | 21M| 1718M| | 28890 (1)| 00:05:47 | Q1,03 | P->P | RANGE |
| 6 | UPDATE | USERS_CHNL_A | | | | | | Q1,03 | PCWP | |
| 7 | PX RECEIVE | | 21M| 1718M| | 28890 (1)| 00:05:47 | Q1,03 | PCWP | |
| 8 | PX SEND HASH (BLOCK ADDRESS)| :TQ10002 | 21M| 1718M| | 28890 (1)| 00:05:47 | Q1,02 | P->P | HASH (BLOCK|
|* 9 | HASH JOIN BUFFERED | | 21M| 1718M| 140M| 28890 (1)| 00:05:47 | Q1,02 | PCWP | |
| 10 | PX RECEIVE | | 22M| 871M| | 9921 (1)| 00:02:00 | Q1,02 | PCWP | |
| 11 | PX SEND HASH | :TQ10000 | 22M| 871M| | 9921 (1)| 00:02:00 | Q1,00 | P->P | HASH |
| 12 | PX BLOCK ITERATOR | | 22M| 871M| | 9921 (1)| 00:02:00 | Q1,00 | PCWC | |
| 13 | TABLE ACCESS FULL | USERS_CHNL_A | 22M| 871M| | 9921 (1)| 00:02:00 | Q1,00 | PCWP | |
| 14 | PX RECEIVE | | 22M| 873M| | 4888 (2)| 00:00:59 | Q1,02 | PCWP | |
| 15 | PX SEND HASH | :TQ10001 | 22M| 873M| | 4888 (2)| 00:00:59 | Q1,01 | P->P | HASH |
| 16 | PX BLOCK ITERATOR | | 22M| 873M| | 4888 (2)| 00:00:59 | Q1,01 | PCWC | |
| 17 | INDEX FAST FULL SCAN | UIDX_USERS_CHNL_NPWD | 22M| 873M| | 4888 (2)| 00:00:59 | Q1,01 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
9 - access("UC"."USER_ID"="UCP"."USER_ID" AND "UC"."CHNL"="UCP"."CHNL")
--2,方案2,使用rowid更新
2.0建立待更新記錄表:
drop table temp_users_chnl_pwd;
create table temp_users_chnl_pwd nologging
as
select uc.rowid rd,uc.password npassword
from users_chnl_a uc
where 1=2;
alter session enable parallel dml;
insert /*+ parallel(tucp 8) */ into temp_users_chnl_pwd tucp
select /*+ parallel(uc 8) parallel(ucp 8) */
uc.rowid rd,ucp.npassword
from users_chnl_a uc,users_chnl_pwd ucp
where uc.user_id=ucp.user_id
and uc.chnl=ucp.chnl
;
commit;
alter session disable parallel dml;
--600 seconds
待更新表rowid排序:
create table temp_users_chnl_pwd_a nologging
as
select * from temp_users_chnl_pwd
where 1=2;
alter session enable parallel dml;
insert /*+ parallel(tucp 8) */ into temp_users_chnl_pwd_a tucp
select /*+ parallel(t 8)*/ *
from temp_users_chnl_pwd t
order by rd
;
commit;
alter session disable parallel dml;
--600 seconds
--2.1批量更新(FORALL)
DECLARE
con_row_limit CONSTANT PLS_INTEGER := 100000;
l_batch INT := 0;
l_count int := 0;
l_rindex BINARY_INTEGER;
l_slno BINARY_INTEGER;
CURSOR cur IS
SELECT rd, npassword FROM temp_users_chnl_pwd;
TYPE rowidtab IS TABLE OF temp_users_chnl_pwd.rd%TYPE INDEX BY PLS_INTEGER;
l_rowidtab rowidtab;
TYPE pwdtab IS TABLE OF temp_users_chnl_pwd.npassword%TYPE INDEX BY PLS_INTEGER;
l_pwdtab pwdtab;
BEGIN
l_rindex := dbms_application_info.set_session_longops_nohint;
OPEN cur;
LOOP
--分批
FETCH cur BULK COLLECT
INTO l_rowidtab, l_pwdtab LIMIT con_row_limit;
EXIT WHEN l_rowidtab.COUNT = 0;
l_count := l_count + l_rowidtab.count;
--更新
FORALL i IN l_rowidtab.FIRST .. l_rowidtab.LAST
UPDATE users_chnl_a
SET password = l_pwdtab(i)
WHERE ROWID = l_rowidtab(i);
COMMIT;
--批次
l_batch := l_batch + 1;
dbms_application_info.set_session_longops(rindex => l_rindex,
slno => l_slno,
sofar => l_batch *
con_row_limit,
target_desc => 'USERS_CHNL');
dbms_output.put_line('Processed:'||l_count);
END LOOP;
COMMIT;
CLOSE cur;
dbms_output.put_line('---OK! Processed:'||l_count);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(dbms_utility.format_error_stack);
COMMIT;
CLOSE cur;
END;
/
待處理記錄沒有針對rowid排序:
==>7800 seconds
待處理記錄針對rowid排序:
==>541 seconds
--2.2 單個更新
DECLARE
con_row_limit CONSTANT PLS_INTEGER := 100000;
l_count INT := 0;
l_rindex BINARY_INTEGER;
l_slno BINARY_INTEGER;
BEGIN
l_rindex := dbms_application_info.set_session_longops_nohint;
FOR x IN (SELECT rd, npassword FROM temp_users_chnl_pwd_a) LOOP
l_count := l_count + 1;
UPDATE users_chnl_a SET password = x.npassword WHERE ROWID = x.rd;
IF (MOD(l_count, con_row_limit) = 0) THEN
COMMIT;
dbms_application_info.set_session_longops(rindex => l_rindex,
slno => l_slno,
sofar => l_count,
target_desc => 'USERS_CHNL');
dbms_output.put_line('Processed:' || l_count);
END IF;
END LOOP;
COMMIT;
dbms_output.put_line('---OK! Processed:' || l_count);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(dbms_utility.format_error_stack);
COMMIT;
END;
/
待處理記錄沒有針對rowid排序:
==>8400 seconds
待處理記錄針對rowid排序:
==>1080 seconds
結果比較:
執行時間(Seconds) 回滾段(undo size,MByte)
直接更新 1800 2,700
中間表-單筆更新-無rowid排序 9000 3
中間表-單筆更新-rowid排序 1680 3
中間表-批量更新-無rowid排序 8400 3
中間表-批量更新-rowid排序 1141 3
結論:
使用“中間表-批量更新-rowid排序”方式更新方式最快,而且所需回滾段空間很少,進度可以監控,可有效控制風險。
3. 非分割槽表dml操作是否可以並行問題:
3.1 會話沒有啟用並行:
update /*+ parallel(t 8) */ users_chnl_a t set password=password;
==>1270 sec
select * from v$px_session
可以看到1*8+1個伺服器程式
3.2 會話啟用並行:
alter session enable parallel dml;
update /*+ parallel(t 8) */ users_chnl_a t set password=password;
commit;
alter session disable parallel dml;
--107.078 sec
--63 sec
--136 sec
select * from v$px_session
可以看到2*8+1個伺服器程式
結論:
非分割槽表支援平行更新,但需要在會話內啟用並行dml.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18922393/viewspace-710488/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- python 批量resize效能比較Python
- 效能比較
- 【MyBatis】幾種批量插入效率的比較MyBatis
- 請比較下for、forEach、for of的效能的效能
- Java中List集合效能比較Java
- 排序演算法效能比較排序演算法
- 批量插入 1 萬條資料,DB 查詢構造器和原生 SQL 效能比較SQL
- Java JIT與AOT效能比較 - foojayJava
- 堆排序和快速排序效能比較排序
- Java Bean Copy元件的效能比較JavaBean元件
- IocPerformance 常見IOC 功能、效能比較ORM
- 利用Pycharm進行程式碼比較更新PyCharm行程
- PostgreSQL、Redis與Memcached的效能比較 - CYBERTECSQLRedis
- Java幾種常用JSON庫效能比較JavaJSON
- 雲主機的硬碟IO效能比較硬碟
- WCF與ASP.NET Core效能比較ASP.NET
- Apache與Nginx的優缺點、效能比較,到底選擇哪個比較好?ApacheNginx
- SQLServer批量更新SQLServer
- Laravel 批量更新Laravel
- MySQL 中的 distinct 和 group by 的效能比較MySql
- 使用 BenchmarkDotNet 比較指定容量的 List 的效能
- Caddy 與 Nginx的基準效能比較 - tjllNginx
- Python、JavaScript和Rust的Web效能比較 - AlexPythonJavaScriptRustWeb
- Spring Boot Native vs Go:效能比較 – Ignacio SuaySpring BootGo
- PHP file_get_contents 與 curl 效能比較PHP
- 四個id 生成器效能比較記錄
- 服務網格Istio、Linkerd和Cilium效能比較
- Stream.toList()和Collectors.toList()的效能比較
- Java基礎(二)- 普通for迴圈、foreach效能比較Java
- 一頓騷操作版本號比較效能提升300%
- NATS訊息傳遞與REST效能比較 | VinsguruREST
- 【譯】Flutter vs React Native vs Native:深度效能比較FlutterReact Native
- js 深比較和淺比較JS
- JAVA中生成隨機數Random VS ThreadLocalRandom效能比較Java隨機randomthread
- Java實體對映工具MapStruct 與BeanUtils效能比較JavaStructBean
- Dapper, Ef core, Freesql 插入大量資料效能比較(二)APPSQL
- 集合差異比較演算法及效能測試演算法
- [譯] 原生 iOS(Swift) 和 React-Native 的效能比較iOSSwiftReact
- 資料庫-批量更新資料庫