delete相關的pl/sql調優
今天開發找到我,說有個問題想徵求一下我的意見。
問題的大體意思是,對目前環境中的兩個表,我們就叫做表a,表b吧,他說根據一個時間欄位去判斷是否為5天前的記錄,但是這個欄位不是索引列欄位。
想問我是否需要新增索引會能極大地提高效能。
對於這個問題沒有肯定的回答,還是取決於資料和表的特性,首先我看了下表a,表b,根據我的印象,這兩個表的資料量都不大,簡單驗證了一下,一個在300萬,一個就10萬左右。所以從資料的角度來看,走全表掃描也是合理的,不需要再建立一個索引了,因為新增加的索引可能會對現有的一些sql語句造成印象,還需要做一些評估才可以。
其次,這兩個表都是核心層的表,這種表的結構式不能輕易修改的,表中的索引,結構都是在很多專案中反覆驗證透過的。所以也是不建議直接增加索引的。
開發的同事得到了希望的答案,過一會我就收到了另外一封郵件。
我一看就發現和開發的同事問我的問題有些關聯。
這一段指令碼是做一個清理相關的操作。最後還嘗試用到了分段提交。
DECLARE
CNT_REC NUMBER(13);
tot_rec number(13);
BEGIN
CNT_REC := 0;
tot_rec := 0;
FOR C1 IN (select *from bpm_context_inst
where objid in (select context_inst2context_inst from bpm_proc_inst where objid in
(select /*+ PARALLEL(coll_entity_history 4) */ proc_inst_id from coll_entity_history where END_TREATMENT_DATE >= SYSDATE -5 and END_TREATMENT_DATE <= SYSDATE -1 )))
LOOP
BEGIN
delete from bpm_context_inst t where t.objid = c1.objid;
END;
CNT_REC := CNT_REC + 1;
tot_rec := tot_rec + 1;
IF CNT_REC = 100 THEN
COMMIT;
CNT_REC := 0;
END IF;
END LOOP;
COMMIT;
END;
這段指令碼讓我有些糾結,因為從這個開發同事的角度來看,這段pl/sql指令碼中一旦確定了coll_entity_history
不需要做索引掃描,可以走全表掃描,他們認為就萬事大吉了。但是我一看到上面的cursor中的那段程式碼,就開始擔心了。
因為他問我的問題似乎還是和這個問題有一定的差距。表bpm_context_inst,bpm_proc_inst這兩個表都是資料量近億的大表。如果從coll_entity_history中得到了太多的資料,外層關聯兩個大表,相比效能也會好不到哪去。如果資料量比較大,直接透過cursor得到快取資料集,做delete還是有一定的效能瓶頸的。對此我也是心有餘悸。可以參見我之前碰到的一個問題。http://blog.itpub.net/23718752/viewspace-1172818/
如果資料量較大,可以嘗試調優一些這段pl/sql。為了能夠準確地評估這段Pl/sql的執行情況,我申請從備份庫中匯出了這幾個表的dump,在測試庫中進行測試。
匯出很順利,但是匯入的時候表bpm_context_inst是相當慢,等了半個小時多,還是沒有什麼反應。
以下是透過imp匯入的一些資料,執行了15分鐘的時候,值匯入了60多萬行,按照這個進度,今天是不用幹別的了。
SQL> select 620540/15/60 from dual;
620540/15/60
------------
689.488889
按照之前的測試impdp效率也好不到哪去,為什麼呢,我一檢視錶結構恍然大悟,原來這個表中含有clob欄位。
好了想模擬測試資料,看來按照目前的情況還是不現實的了。
我們來顯分析一下資料。既然是需要按照每隔5天來做資料的清理,來看看這些天來的資料情況。 以下是我分析得到的近50天來的資料情況,每天的相關資料量其實還是很小的。
65788 |
2-Mar-15 |
30787 |
7-Feb-15 |
7987 |
11-Mar-15 |
33929 |
6-Feb-15 |
29370 |
10-Feb-15 |
53211 |
26-Feb-15 |
62 |
23-Mar-15 |
3382 |
17-Mar-15 |
4443 |
4-Mar-15 |
12095 |
13-Feb-15 |
8789 |
12-Feb-15 |
3074 |
13-Mar-15 |
7598 |
20-Feb-15 |
2239 |
8-Mar-15 |
2627 |
14-Mar-15 |
7726 |
24-Feb-15 |
6330 |
22-Feb-15 |
6537 |
19-Feb-15 |
7158 |
21-Feb-15 |
2872 |
7-Mar-15 |
7419 |
18-Feb-15 |
5104 |
9-Mar-15 |
46094 |
27-Feb-15 |
18377 |
4-Feb-15 |
7571 |
16-Feb-15 |
4145 |
6-Mar-15 |
4006 |
16-Mar-15 |
20 |
24-Mar-15 |
7578 |
17-Feb-15 |
29062 |
9-Feb-15 |
6821 |
15-Feb-15 |
886 |
18-Mar-15 |
9221 |
25-Feb-15 |
3822 |
10-Mar-15 |
953 |
20-Mar-15 |
62115 |
5-Mar-15 |
2484 |
15-Mar-15 |
26311 |
8-Feb-15 |
6997 |
14-Feb-15 |
16572 |
28-Feb-15 |
68 |
26-Mar-15 |
11202 |
11-Feb-15 |
9251 |
1-Mar-15 |
5056 |
22-Mar-15 |
2869 |
21-Mar-15 |
29508 |
5-Feb-15 |
1 |
25-Mar-15 |
493 |
19-Mar-15 |
55572 |
3-Mar-15 |
7469 |
23-Feb-15 |
5008 |
12-Mar-15 |
按照這個資料量,原本存在效能隱患的那段pl/sql看起來也順眼多了。但是細細看來,還是有個硬傷。
就是cursor定義的部分,根據pl/sql的實現目標,沒有用到clob欄位,所以是不相關的。可以在cursor的部分直接過濾掉。
C1 IN (select *from bpm_context_inst
where objid in (select context_inst2context_inst from bpm_proc_inst where objid in
(select /*+ PARALLEL(coll_entity_history 4) */ proc_inst_id from coll_entity_history where END_TREATMENT_DATE >= SYSDATE -5 and END_TREATMENT_DATE <= SYSDATE -1 )))
直接改為select objid from bpm_context_inst就可以了
最後我給出了兩種意見,第一種是上面的pl/sql完全可以透過一句delete語句來完成,至於他們關注的分段提交,其實在這個場景中,影響是忽略不計,實際上一次提交效能還要好於分批提交。
即
delete bpm_context_inst
where objid in (select context_inst2context_inst from bpm_proc_inst where objid in
(select /*+ PARALLEL(coll_entity_history 4) */ proc_inst_id from coll_entity_history where END_TREATMENT_DATE >= SYSDATE -5 and END_TREATMENT_DATE <= SYSDATE -1 ))
另外一種就是把cursor定義的部分做一些改動,去除clob欄位。對於cursor的提升是還是很大的。
對於這兩種意見,開發同事說自己確實考慮得不夠周到,不過為了避免給客戶造成更多的困擾,還是選用第二種方案。
這個問題帶給我的啟示就是可能大家問你的問題是一個場景,但是和另外一個場景聯絡起來,原來的一些推論就不是那麼肯定了。就比如這個問題中,開發確定不需要索引對於查詢這個表效能影響不大,但是並不意味著在和其他的大表關聯時沒有問題。如果那種情況發生,還需要做一些額外的最佳化工作。根據資料量最後得知,變更的資料量很小,所以這個也算是化險為夷吧。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1475198/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 循序漸進調優union相關的sqlSQL
- PL/SQL相關的資料字典SQL
- 【sql調優之執行計劃】in相關的operationSQL
- 生產系統pl/sql調優案例SQL
- Oracle PL/SQL 優化與調整 – PL/SQL Native Compilation 說明OracleSQL優化
- sql優化相關SQL優化
- pl/sql dev連線oracle相關問題SQLdevOracle
- Oracle PL/SQL 優化與調整 -- Bulk 說明OracleSQL優化
- PLSQL Language Reference-PL/SQL概覽-PL/SQL的優點SQL
- 在pl/SQL中呼叫logminer相關檢視的問題SQL
- delete 資料很慢調優解決delete
- delete_partition_guangzhou.pldelete
- SQL調優SQL
- PL/SQL 事務持久化異常 / PL/SQL commit優化SQL持久化MIT優化
- PL/SQL優化一例SQL優化
- MS SQL SERVER索引優化相關查詢SQLServer索引優化
- SQL SERVER 日期相關性優化選項SQLServer優化
- sql相關SQL
- 資料庫效能優化-索引與sql相關優化資料庫優化索引SQL
- sql調優1SQL
- oracle sql調優OracleSQL
- 關於pl/sql的程式碼保護SQL
- 有關效能調整的查詢和pub上的一個sql調優!SQL
- 【調優篇基本原理】優化器相關引數配置優化
- MySQL調優篇 | SQL調優實戰(5)MySql
- 一條大sql的調優SQL
- 關於pl/sql中的繫結變數SQL變數
- Teradata SQL調優SQL
- 調整PL/SQL程式碼加速執行(2例)SQL
- Oracle’s DBMS_Profiler:PL/SQL 效能調整 (轉)OracleSQL
- Oracle調優相關的各種命中率、使用率彙總Oracle
- PL/SQLSQL
- SQL Server 日期相關SQLServer
- delete_partition.pl 刪除分割槽delete
- Oracle PL/SQL 關於遊標的介紹OracleSQL
- SQL__DELETESQLdelete
- MySQL索引和SQL調優MySql索引
- SQL調優真實案例SQL