利用 rowid 提公升update效能

2021-08-31 15:26:18 字數 2686 閱讀 9959

能不能想辦法 提公升一下如下update語句的效能

update opt_acct_fdim a

set acct_skid = (select acct_skid

from opt_acct_fdim_bkp b

where a.acct_id = b.acct_id);

select count(*) from opt_acct_fdim; -------這個表 有 226474 條資料

select count(*) from opt_acct_fdim_bkp; ------ 這個表 有 227817 條資料

select count(*)

from opt_acct_fdim a, opt_acct_fdim_bkp b

where a.acct_id = b.acct_id

and a.acct_skid <> b.acct_skid; -------要更新 226474 條

那麼現在已經很清楚了,業務邏輯就是根據 根據2個表的acct_id 字段關聯,然後根據b表的字段update a表,那麼這裡呢 要更新整個a表

update的執行計畫我們就不用看了,肯定是hash join,開發人員說 這個update 跑了30分鐘,還沒完成,其實我估計 這個sql至少得1小時才能跑完。

其實,select 語句是很好優化的,但是update,delete這樣的sql, 如果要想從sql上面優化,幾乎不可能,優化update,delete我們要用pl/sql來實現。

對於我們這裡的update語句,我們可以利用rowid 來快速更新,pl/sql **如下:

sql> declare

2 cursor cur_b is

3 select

4 b.acct_id, b.acct_skid, a.rowid row_id

5 from opt_acct_dim a, opt_acct_dim_bkp b

6 where a.acct_id = b.acct_id

7 order by a.rowid; ---如果表的資料量不是很大,可以不用 order by rowid

8 v_counter number;

9 begin

10 v_counter := 0;

11 for row_b in cur_b loop

12 update opt_acct_dim

13 set acct_skid = row_b.acct_skid

14 where rowid = row_b.row_id;

15 v_counter := v_counter + 1;

16 if (v_counter >= 1000) then

17 commit;

18 v_counter := 0;

19 end if;

20 end loop;

21 commit;

22 end;

23 /

pl/sql procedure successfully completed.

elapsed: 00:01:21.58

現在多快啊,1分22秒搞定

其實,以前的update就相當於下面的pl/sql**:

declare

cursor c_update is

select b.acct_skid, a.acct_id

from opt_acct_fdim a, opt_acct_fdim_bkp b

where a.acct_id = b.acct_id;

v_counter number;

begin

v_counter := 0;

for v_row in c_update loop

update opt_acct_fdim

set acct_skid = v_row.acct_skid

where acct_id = v_row.acct_id; ---注意,這裡沒有rowid

v_counter := v_counter + 1;

if (v_counter >= 1000) then

commit;

v_counter := 0;

end if;

end loop;

commit;

end;

/我自己測試了一下上面的pl/sql **,跑了30分鐘沒跑完,為什麼跑這麼久呢?

其實原因就在於這裡:

update opt_acct_fdim

set acct_skid = v_row.acct_skid

where acct_id = v_row.acct_id;

因為缺少 rowid定位,那麼又會對錶進行全表掃瞄,而且每更新一行就會去做全表掃瞄。

而我們利用rowid定位block,那麼不用 全表掃瞄了 效能提公升上 百倍。

12 update opt_acct_dim

13 set acct_skid = row_b.acct_skid

14 where rowid = row_b.row_id;

其實這本書 oracle database 10g pl/sql 程式設計 ---清華大學出版社 p132頁 裡面就有這個方法

itpub 這篇帖子: 也提到過這個方法

總結:對於大批量的update,delete,我們可以利用rowid 來進行優化,效能往往提公升 上百倍。

分段表rowid 利用ROWID 快速更新單錶記錄

對於普通表 實現 update t pm deposit his b set flag substr flag,1,8 4 case when term 365 then 1 else 2 end as flag where b.data date 20130101 declare cursor c...

利用NSCache提公升效率

解決辦法就是把nsdata物件快取起來,先從nscache裡面讀取資料,然後再從檔案系統獲取資料,提高效率。方法如下 步驟1 需要乙個單例的nscache,由於我們的fileutil本來就是單例的,所以只是需要在初始化fileutil的時候例項出乙個nscache就行了。cache nscache ...

利用NSCache提公升效率

不過在模擬器中模擬記憶體警告時,快取不會做清理動作 為了確保接收到記憶體警告時能夠真正釋放記憶體,最好呼叫一下 removeallobjects 方法 nscache 是執行緒安全的,在多執行緒操作中,不需要對 cache 加鎖 nscache 的 key 只是做強引用,不需要實現 nscopyin...