批量更新資料方法比較測試
很多情況下,我們會遇到大資料量的批量更新要求,下面,我就來按照rowid的方式(這應該是最快的方法),來比較幾種處理方式之間的效能差異,由於機器效能(PC機)及時間原因,這裡只准備了460W條資料,比較各種方案迴圈處理的時間,比較結果。
SQL> select count(1) from testA;
COUNT(1)
----------
4643600
SQL> set timing on
第一種情況,無序rowid的遊標迴圈更新:
SQL> declare
cursor upd_cursor is
select rowid as row_id from testA;
rowd varchar(30);
v_counter number;
begin
open upd_cursor;
loop
fetch upd_cursor
into rowd;
exit when upd_cursor%notfound;
execute immediate 'update testA set flag=:f where rowid=:r'
using 1, rowd;
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
close upd_cursor;
commit;
end;
/
cursor upd_cursor is
select rowid as row_id from testA;
rowd varchar(30);
v_counter number;
begin
open upd_cursor;
loop
fetch upd_cursor
into rowd;
exit when upd_cursor%notfound;
execute immediate 'update testA set flag=:f where rowid=:r'
using 1, rowd;
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
close upd_cursor;
commit;
end;
/
PL/SQL 過程已成功完成。
已用時間: 00: 05: 46.78
第二種情況,有序rowid的遊標迴圈更新:
SQL> declare
cursor upd_cursor is
select rowid as row_id from testA order by rowid;
rowd varchar(30);
v_counter number;
begin
open upd_cursor;
loop
fetch upd_cursor
into rowd;
exit when upd_cursor%notfound;
execute immediate 'update testA set flag=:f where rowid=:r'
using 1, rowd;
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
close upd_cursor;
commit;
end;
/
cursor upd_cursor is
select rowid as row_id from testA order by rowid;
rowd varchar(30);
v_counter number;
begin
open upd_cursor;
loop
fetch upd_cursor
into rowd;
exit when upd_cursor%notfound;
execute immediate 'update testA set flag=:f where rowid=:r'
using 1, rowd;
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
close upd_cursor;
commit;
end;
/
PL/SQL 過程已成功完成。
已用時間: 00: 05: 30.03
第三種情況,無序rowid的bulk collect更新:
SQL> declare
type objecttab is table of varchar2(20);
rowd objecttab;
cursor upd_cursor is
select rowid as row_id from testA;
v_counter number;
begin
open upd_cursor;
fetch upd_cursor bulk collect
into rowd;
close upd_cursor;
for i in rowd.first .. rowd.last loop
execute immediate 'update testA set flag=:f where rowid=:r'
using 2, rowd(i);
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
commit;
end;
/
type objecttab is table of varchar2(20);
rowd objecttab;
cursor upd_cursor is
select rowid as row_id from testA;
v_counter number;
begin
open upd_cursor;
fetch upd_cursor bulk collect
into rowd;
close upd_cursor;
for i in rowd.first .. rowd.last loop
execute immediate 'update testA set flag=:f where rowid=:r'
using 2, rowd(i);
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
commit;
end;
/
PL/SQL 過程已成功完成。
已用時間: 00: 04: 29.80
第四種情況,有序rowid的bulk collect更新:
SQL> declare
type objecttab is table of varchar2(20);
rowd objecttab;
cursor upd_cursor is
select rowid as row_id from testA order by rowid;
v_counter number;
begin
open upd_cursor;
fetch upd_cursor bulk collect
into rowd;
close upd_cursor;
for i in rowd.first .. rowd.last loop
execute immediate 'update testA set flag=:f where rowid=:r'
using 2, rowd(i);
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
commit;
end;
/
type objecttab is table of varchar2(20);
rowd objecttab;
cursor upd_cursor is
select rowid as row_id from testA order by rowid;
v_counter number;
begin
open upd_cursor;
fetch upd_cursor bulk collect
into rowd;
close upd_cursor;
for i in rowd.first .. rowd.last loop
execute immediate 'update testA set flag=:f where rowid=:r'
using 2, rowd(i);
if (v_counter >= 1000) then
commit;
v_counter := 0;
end if;
end loop;
commit;
end;
/
PL/SQL 過程已成功完成。
已用時間: 00: 04: 41.76
最後,再來看看forall,對於這種迴圈,建議更新的資料量不要太大,效果還是可以的,對於這裡的資料量已經不合適。
SQL> declare
type objecttab is table of varchar2(20);
rowd objecttab;
cursor upd_cursor is
select rowid as row_id from testA order by rowid;
v_counter number;
begin
open upd_cursor;
fetch upd_cursor bulk collect
into rowd;
close upd_cursor;
forall i in rowd.first .. rowd.last execute immediate
'update testA set flag=:f where rowid=:r' using 1,
rowd(i)
;
commit;
end;
/
type objecttab is table of varchar2(20);
rowd objecttab;
cursor upd_cursor is
select rowid as row_id from testA order by rowid;
v_counter number;
begin
open upd_cursor;
fetch upd_cursor bulk collect
into rowd;
close upd_cursor;
forall i in rowd.first .. rowd.last execute immediate
'update testA set flag=:f where rowid=:r' using 1,
rowd(i)
;
commit;
end;
/
手動給停止了,這種資料級一次性提交太不合適了。
總結:對於這個資料量級的更新,是否按rowid的順序去更新,對效能的影響不是很大,可能和我資料的儲存有關(測試資料是我一次性插入的,可能分佈本身就很連續了)。若是那種分佈不連續,而且資料量很大的話,按rowid順序會去讀取更新快些。還有,貌似bulk collect適當使用,效率會比遊標的效率更高。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-684553/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 資料庫-批量更新資料庫
- 如何批量更新資料
- pymysql批量更新資料MySql
- python 批量resize效能比較Python
- oracle批量新增更新資料Oracle
- Apache Pulsar 與 Kafka 效能比較:延遲性(測試方法)ApacheKafka
- Ibatis批量更新資料(mysql資料庫)BATMySql資料庫
- 主流資料庫比較資料庫
- 圖資料庫比較資料庫
- 【MyBatis】幾種批量插入效率的比較MyBatis
- 滲透測試與自動化安全測試工具比較
- HHDESK資料夾比較功能
- difflib: Python 比較資料集Python
- 批量插入 1 萬條資料,DB 查詢構造器和原生 SQL 效能比較SQL
- MySQL 批量更新、刪除資料shell指令碼MySql指令碼
- initialize方法與load方法比較
- 77種資料建模工具比較
- 集合差異比較演算法及效能測試演算法
- ==和equals方法的比較
- 淺談前端MOCK資料工具比較前端Mock
- 利用Pycharm進行程式碼比較更新PyCharm行程
- 程式碼覆蓋率與測試覆蓋率比較
- mysql資料庫中decimal資料型別比較大小MySql資料庫Decimal資料型別
- mysql根據查詢結果批量更新多條資料(插入或更新)MySql
- ios12 測試版更新方法iOS
- mongodb資料遷移2種方式比較MongoDB
- 比較 Apache Hadoop 資料儲存格式 - techwellApacheHadoop
- influxdb與傳統資料庫的比較UX資料庫
- 常見的web系統測試管理工具比較Web
- SQLServer批量更新SQLServer
- Laravel 批量更新Laravel
- 萬能測試用例及測試用例編寫方法(待更新)
- 測試資料
- TestContainers:現代資料庫的測試方法 -GunduAI資料庫
- Cesium 比較常用的幾個方法
- jQuery的prop和attr方法比較jQuery
- BigDecimal的equals() 和 compareTo() 方法比較Decimal
- K8S資料保護工具比較K8S
- 測試速度比較:Selenium vs Playwright vs Cypress vs Puppeteer vs TestCafe