誤用append案例一則

這是某客戶關鍵系統的一個TOP SQL:
sql

INSERT INTO /*+ append */ TF_B_OCS_BATDEAL (...... )性能優化

SELECT  F_SYS_GETSEQID(EPARCHY_CODE, 'batch_id')微信

......session

FROM TF_F_USER B併發

WHERE B.REMOVE_TAG = '0' AND USER_ID = :B1 AND B.USER_STATE_CODESET = '0' AND oracle

LENGTH(SERIAL_NUMBER) = '11' AND SERIAL_NUMBER LIKE '1%' AND app

 NOT EXISTS 性能

(優化

  SELECT 1spa

  FROM TF_F_USER_SHARE_RELA C

  WHERE B.USER_ID = C.USER_ID_B AND C.END_DATE > SYSDATE

 );

根據下圖sqlhc獲取的信息,該SQL平均每次插入不到一條記錄,每半小時執行10萬次左右。



爲何cpu時間消耗不多,大部分等待時間是application等待?

sqlhc裏面也有交待:

這些wait class是application的具體等待事件是enq:TM - contention,也就是表鎖。在AWR報告的TOP 10事件中,也出現了這個事件,並且佔DB time的4.6%,可見一個SQL就對系統形成了較大的影響:


這個表鎖是如何生成的?


罪魁禍首就是SQL中使用的append Hint。


append的Hint通常使用在insert select語句,插入大量結果集的時候,採用直接路徑(direct path)在表的高水位線以上直接寫入數據。在沒有commit以前,sql會一直持有表鎖。


這個Hint在數據倉庫的SQL中使用較多,一次插入記錄幾十萬以上,執行頻率低。


可是,在本例OLTP系統中,頻繁執行並且插入少許記錄的SQL也使用了append的hint,形成的後果就是:


一、sql執行效率低,大量的表鎖等待,併發越多等待越嚴重。

二、插入的表TF_B_OCS_BATDEAL,有大量的空間被浪費,每插入一條記錄都會佔用一個block。並且即便有大量記錄被delete,這些高水位線如下的空閒塊不會被從新使用。


解決方法:

   這種頻繁執行,每次插入少許記錄的狀況,不能使用append,必須立刻去掉這個hint。


補充:

     並行DML開啓時,默認啓用append插入模式。



insert /*+ parallel(4) */ into xxx  select ....

這個SQL默認並無開啓並行DML,只是後面的select部分使用了並行,這種狀況沒有使用append。


alter session enable parallel dml; --啓用並行DML

insert /*+ parallel(4) */ into xxx select

這時就啓用了並行DML,不加append的hint,默認也是append插入模式。





本文分享自微信公衆號 - 老虎劉談oracle性能優化(sql_tigerliu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索