2014-05-23 89 views
5

一個java程序正在批量插入Oracle表中。它適用於100-200條記錄,但其掛起的記錄超過4000條。爲什麼使用INSERT/* + APPEND * /?

當我檢查查詢時,其中有INSERT /*+APPEND*/

什麼是INSERT /*+APPEND*/以及爲什麼它在INSERT查詢中使用?程序是否因爲這件事而懸掛?

+0

/* + APPEND * /我認爲這只是一條評論。 –

+6

[該提示在文檔中進行了說明](http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements006.htm#sthref495)。你有多個進程同時插入,還是表中沒有提交數據? –

+0

@AlexPoole是的,多個線程同時訪問表 –

回答

4

這是一個SQL優化器提示。在你的情況下,它很可能沒有任何影響。也許這是一個不成熟的優化。

該提示應該實施所謂的直接路徑插入,它繞過Oracle的緩衝區緩存並將數據直接寫入數據文件。數據被追加到高水位標記(HWM)之外 - 忽略表格的可用空間圖,沒有觸發器被觸發,也沒有檢查到任何限制。另一方面,這種類型的插入件是阻塞的。只有一個會話可以同時在特定的表上使用它。

從文檔的摘錄:

「APPEND提示僅支持與 INSERT語句,而不是VALUES子句的子查詢語法如果指定APPEND 提示與VALUES子句,它。被忽略,傳統的插入 將被使用。要使用直接路徑INSERT與VALUES子句,請參閱 爲「APPEND_VALUES提示」當你使用INSERT作爲 SELECT語句

此提示僅適用

當您插入值時,Oracle默默忽略它。較新的Oracle版本也支持APPEND_VALUES提示。

如果要驗證正在使用的提示正在打開Toad或SQL Developer,請選擇會話瀏覽器,找到該特定會話並且它是當前的SQL和執行計劃。當你在執行計劃中看到類似"INSERT into TABLE CONVENTIONAL"時,提示將被忽略。如果您看到"INSERT as SELECT",那麼您正在使用直接路徑加載。

+0

「此提示僅在您使用INSERT作爲SELECT語句時纔有效」。你確定只適用於這種情況嗎? –

+2

我認爲就是這樣。打開Toad或SQL Developer,選擇會話瀏覽器,找到那個特定的會話,它是當前的SQL和exec計劃。當你在執行計劃中看到類似「INSERT into TABLE CONVENTIONAL」的提示時,該提示將被忽略。如果您看到「INSERT as SELECT」,那麼您正在使用直接路徑加載。 – ibre5041

+3

摘自docs:「APPEND提示只支持INSERT語句的子查詢語法,而不支持VALUES子句。如果用VALUES子句指定APPEND提示,它將被忽略並使用常規插入。帶VALUES子句的直接路徑INSERT,請參閱「APPEND_VALUES提示」。「 – ibre5041

3

insert通常查找表中的第一個空白區域以添加新記錄。雖然這節省了空間,但有時可能會減慢操作速度。

/*+APPEND*/是一個hint這導致insert語句永遠,因爲缺乏一個更好的術語,將新插入的行追加到表的末尾。這可能會浪費一些空間,但通常會更快。如果您知道在表格中間沒有太多的空白區域(例如,您沒有執行大量的delete s和update s),則此功能特別有用。

+2

如果表[空間]設置爲NOLOGGING或DB處於NOARCHIVELOG模式,則APPEND提示將只會減少重做生成。 oracle-base.com/articles/misc/append-hint.php – user584583

1

這是一個ORACLE compliler提示。這是爲了一個目的,而不是一個評論。 這個提示在那裏用來加速插入,所以我不認爲這是掛起程序的原因。

然而,請詢問您的DBA在這個表是使用表來檢查可用空間。(你的DBA就會明白這一說法更好:))

有可能是一個問題,有可用的非常少的空間用於該表空間中的任何其他插入,dba應該能夠解決該插入。

爲什麼可能有更少的空間可用?因爲APPEND提示浪費了空間,正如@Mureinik的上述回答所解釋的那樣,如果該表中存在太多頻繁插入的提示,則可能會出現問題。

0

我不知道「加速」插入,但我已經明確地發現了這個提示,是的,這是Oracle稱之爲的 - 不是評論 - 對於維護記錄順序非常有用從一個表執行插入到另一個,當我與ORDER BY配對命令結尾:

INSERT /*+ append */ INTO MYAPP.COUNTRIES (ID, CODE, NAME) 
SELECT ID, CODE, NAME FROM MYAPP.OLD_COUNTRIES_TABLE ORDER BY NAME ASC; 
COMMIT; 

我已經得到了高射炮,這只是一個巧合(見SO this thread),但我現在,它使用了很多次,這至少是我結束的成果。如果您使用INSERTORDER BY,但而不是附加提示,ORDER BY被忽略,並且完全無用,以確保可以根據它們插入的順序檢索記錄(請參閱my proof in my answer, here)。

相關問題