能不能想辦法 提公升一下如下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...