在上篇《java 併發:多線程鎖計數器》中提到過,在工作中碰到一個較大數據量的處理模塊。在上篇中使用多線程解決了數據導入的問題,而在數據導入後碰到了較大數據量的邏輯處理和更新問題,爲了在儘量短的時間內完成數據處理,我們開發組將整個數據處理過程拆分成兩個存儲過程和一段java代碼。
我負責其中一個存儲過程,整個存儲過程的邏輯就是通過數據的Code字段規則,分析數據與數據之間是否存在父子關係,並將這種關係通過Parent_Id實體化。
存儲過程完成後速度依然很慢在4分鐘左右,在不斷的探索和測試後終於將時間縮短到2-3s內。在此過程中學到了很多,在此記錄。
存儲過程之優化
存儲過程核心Code
--遍歷WBS編碼所有長度,即所有層級
for i in code_length loop
m_num := i.clength - s_code;
for frecord1 in (select *
from sgt_wbs
where PLAN_ID = planId
and length(CODE) = i.clength) loop
-- 如果爲頂級編碼則只更新層級
if (i.clength = min_code) then
update sgt_wbs t
set t.node_level = n_level
where length(code) = i.clength;
exit;
end if;
--更新WBS節點的parent_id
update sgt_wbs t
set t.parent_id = (select id
from sgt_wbs
where code = substr(frecord1.code,
0,
i.clength - m_num)
and plan_id = planId),
t.node_level = n_level
where t.CODE = frecord1.code
and t.plan_id = planId;
end loop;
commit;
s_code := i.clength;
n_level := n_level + 1;
end loop;
存儲過程測試及運行
1. 存儲過程運行
begin
-- Call the procedure
sgt_update_pid(planid => :planid);
end;
2. 存儲過程的測試
整個過程使用的數據庫連接工具爲PL/SQL
-
首先在存儲過程上右擊選中添加調試信息,然後再次選中測試
-
然後添加變量數據,並執行
-
頂部工具欄中常用工具
常用的就兩個按鈕:按鈕1和按鈕2 ,按鈕1爲直接運行存儲過程,按鈕2爲單步執行存儲過程,類似java的debug。按鈕1 可以直接測試存儲過程是否能夠執行成功,而按鈕2一般爲在存儲過程出錯的過程中進行單步調試
-
單步調試
在調試過程中可以添加觀察變量,可以觀察變量在運行過程中值得變化,便於錯誤排查和調試
3. 存儲過程概覽圖
在存儲過程中想要查看整個代碼用時情況需要使用概覽圖
-
選中概覽圖按鈕
如果想要查看存儲過程的時間分佈是無法同時單步調試的,需要直接執行
-
執行
在使用概覽圖的功能時是不能測試的,需要直接運行
-
查看執行計劃
在執行後,可以在頂部選擇概覽圖查看整個存儲過程中時間分部,並對耗時部分進行鍼對的優化
存儲過程優化
在測試通過並使用概覽圖分析後發現了影響時間的code
1.分析耗時code
我們可以發現存儲過程中大部分時間都消耗在更新語句中,在單獨對此語句做分析,並獲取該語句的執行計劃(F5)
- 可優化代碼
update sgt_wbs t
set t.parent_id = (select id
from sgt_wbs
where code = substr(frecord1.code,
0,
i.clength - m_num)
and plan_id = planId),
t.node_level = n_level
where t.CODE = frecord1.code
and t.plan_id = planId;
-
執行計劃
通過執行計劃,我們可以發現更新過程中 子查詢是最耗時的操作,所以我們優化的重點放在了這個子查詢中。
但是子查詢語句很簡單,並沒有優化空間,所以這裏我們爲查詢字段創建了索引來加快查詢速度
2.創建索引並測試
當創建索引後,再次測試存儲過程,原來需要360多秒的時間,縮短到了2-3秒鐘,說明優化是有效的,並解決了數據處理時間過長的問題
多線程的限制
在上篇文章中,使用多線程優化數據導入後,還想要在加快數據導入速度,最直接的反應是提高線程數。所以在此思想上做了一些列的測試
- 數據量16000條
百分比(鎖) | 線程數 | 數據校驗 | 時間 |
---|---|---|---|
無 | 7 | 有 | 2.30m |
無 | 7 | 無 | 32s |
有 | 7 | 有 | 2.40m |
無 | 14 | 有 | 2.33m |
無 | 14 | 無 | 29s |
有 | 14 | 有 | 2.40m |
通過比對測試發現線程數的增多在無數據校驗和變量鎖的情況下,多線程會提升導入速度,減少時間,但是一旦有了變量鎖和校驗,一倍多的線程速度反而慢了下來。
測試直觀的表明,線程的確能提升導入效率,但是是有極限的,一旦超過最優線程數量,數據導入速度反而會出現下降的情況。可見線程是有限制的,一定要將線程數定在一個合理的範圍內,否則過多的線程不但會拖慢運行速度還會消耗服務器資源,導致整個應用響應變慢