我試圖找到一種更好的方法,將數據從表中拖入另一個作爲更大處理項目的一部分。我認爲我可以通過BULK COLLECT和FORALL做到這一點,並拿起顯着的速度,但我不認爲我可以使用BULK COLLECT處理單個列引用...我有一個數據/應用程序遷移項目(MSSQL到Oracle 11.2)繼承。我試圖優化和檢查端到端......該過程的第一步是將舊數據(數據庫表,4.5M記錄,170列,全部以字符串格式)導入到另一個表中。Oracle數據轉換 - Bulk/ForALL將不起作用
初始轉換是基於遊標的,逐行循環,每列至少有一個函數用於清除/轉換。它很有效,但在測試系統上花費了很長時間 - 超過12個小時將450萬條記錄從一張表翻譯到另一張表,並且功能非常簡單。 在我有權訪問的本地實現中,他們在220k條記錄中限制了13000個單元ID號碼ID。
我在筆記本電腦上設置了一個更有限的開發系統,用於測試替代技術 - 並且可以獲得5倍以上的導入速度,但仍然是光標/逐行。我已將表格設置爲NOLOGGING並使用APPEND提示。我測試過/沒有索引。我不能用這個尺寸表做SELECT INTO - 它只是窒息而已。
有沒有另一種/更好的技術?我還能如何提高轉換速度?我是否做錯了W/BULK COLLECT(即有沒有辦法參考單個字段?)
如果有人有任何見解,請切入!我包括一個非常簡潔的程序版本,所以我可以顯示我的使用嘗試。同樣的事情(非常多)作爲普通的遊標循環來運行,而不是FORALL和(i)下標。我得到的錯誤是ORA-00913:太多的值。我已經完成了完整的插入語句,將字段與值進行匹配。我檢查了數據轉換函數 - 它們用於常規列作爲參數。我想知道如果他們不工作w/BULK COLLECT和/或FORALL,因爲下標?
更新的信息: 這是一個限制訪問的系統上,並且到現在爲止(等待帳戶),我一直有遠程診斷「真實」(客戶)DEV系統,通過對運行一個本地系統 - 分析代碼,數據,時間等。我的建議是由另一位開發人員提供的,他們會將結果反饋給我。認真。然而... @Mark,@Justin - 通常情況下,我會擺脫任何遊標不是?絕對?需要的地方,並儘可能使用SELECT INTO。這通常是我的第一個關於舊PL/SQL代碼的建議......(「Why,So.Cursor?」穿着Joker化妝)。這是我在本地系統上嘗試的第一件事,但它只是減慢了服務器的爬行速度,我放棄了測試。那是在實施減少的NOLOGGING之前 - 這是我嘗試觸摸開發系統時的嘗試。
在查看時序,查詢,連接,索引和哭泣之後,我推薦使用NOLOGGING並將其轉換爲INSERT/* + APPEND */- ,這是在其他進程中購買的時間,主要是建立在聯接之外的表。
re:「OID < ='000052000'」 - 當他們在cust dev系統中設置第一個轉換的代碼時,他們必須限制他們從PMS_OHF錶轉換的記錄數量。最初,他們可以在合理的時間內獲得13000個人員標識符進行處理。那13000個ID將會在大約22萬條記錄中,所以,當我上船時他們就是這麼做的。一些重寫,加入更正,和NOLOGGING /插入附加做了足夠大的差別,他們繼續。在本地系統上,我認爲13000太小 - 我認爲我沒有對遺留結果進行有意義的比較 - 所以我將其升高並加以提升。我應該勇敢地嘗試在筆記本電腦開發系統上進行全面轉換 - 在這裏我至少可以通過EM觀察發生了什麼......政府不會允許他們的DBA使用它。
BIGGER信息(!?): - 再次回味00913錯誤,並回想起其他項目後,我意識到,當一個以上的元素被傳遞到預期的單個元素的函數先前的錯誤是...它指向我tp我試圖在BULK COLLECT循環中使用下標字段名稱。我重新觀看了幾個Steven Feuerstein YT演示文稿,我認爲它終於沉入其中。簡單的Web示例...我正在水平製作我的類型,而不是垂直(反之亦然)...爲了讓我的函數調用工作,我認爲我必須爲每個字段和該類型的ARRAY/TABLE做一個TYPE。突然間(170次)我在考慮一些關於手動並行的Tom Kyte課程,並要求wx我可以訪問新的(11.2?)DBMS_PARALLEL_EXECUTE接口 - 我懷疑它。此外,不知道更多關於客戶開發系統,除了最好的描述「不足」之外,我不知道wx // ism會是一個巨大的幫助。我需要閱讀// ism
我所知道的是,我必須完成一些完整的運行,否則我不會感到舒服,認爲我們的結果與傳統結果「足夠接近」。對於我們的測試,我們可能沒有太多的選擇。
PROCEDURE CONVERT_FA IS
CURSOR L_OHF IS -- Cursor used to get SOURCE TABLE data
SELECT *
FROM TEST.PMS_OHF -- OHF is legacy data source
where OID <= '000052000' -- limits OHF data to a smaller subset
ORDER BY ID ;
L_OHF_DATA TEST.PMS_OHF%ROWTYPE;
L_SHDATA TEST.OPTM_SHIST%ROWTYPE;
Type hist_Array is table of TEST.PMS_OHF%ROWTYPE;
SHF_INPUT hist_array ;
Type Ohist_Array is table of TEST.OPTM_SHIST%ROWTYPE;
TARG_SHIST ohist_Array ;
n_limit number := 1000 ;
BEGIN
begin
OPEN L_OHF;
LOOP
FETCH L_OHF BULK COLLECT INTO SHF_INPUT LIMIT n_limit ;
FORALL i in 1 .. n_limit
INSERT INTO TEST.OPTM_SHIST
( -- There are 170 columns in target table, requiring diff't xformations
RECORD_NUMBER , UNIQUE_ID , STRENGTH_YEAR_MONTH , FY , FM , ETHNIC ,
SOURCE_CODE_CURR , SOURCE_CODE_CURR_STAT ,
-- ... a LOT more fields
DESG_DT_01 ,
-- and some place holders for later
SOURCE_CALC , PSID , GAIN_CURR_DT_CALC
)
values
(-- examples of xformatiosn
SHF_INPUT.ID(i) ,
'00000000000000000000000' || SHF_INPUT.IOD(i) ,
TEST.PMS_UTIL.STR_TO_YM_DATE(SHF_INPUT.STRYRMO(i)) ,
TEST.PMS_UTIL.STR_TO_YEAR(SHF_INPUT.STRYRMO(i)) ,
TEST.PMS_UTIL.STR_TO_MONTH(SHF_INPUT.STRYRMO(i)) ,
TEST.PMS_UTIL.REMOVE_NONASCII(SHF_INPUT.ETHNIC(i)) ,
-- ... there are a lot of columns
TEST.PMS_UTIL.REMOVE_NONASCII(SUBSTR(SHF_INPUT.SCCURPRICL(i),1,2)) ,
TEST.PMS_UTIL.REMOVE_NONASCII(SUBSTR(SHF_INPUT.SCCURPRICL(i),3,1)) ,
-- an example of other transformations
(case
when (
(
SHF_INPUT.STRYRMO(i) >= '09801'
AND
SHF_INPUT.STRYRMO(i) < '10900'
)
OR
(
SHF_INPUT.STRYRMO(i) = '10901'
AND
SHF_INPUT.DESCHGCT01(i) = '081'
)
)
then TEST.PMS_UTIL.STR_TO_DATE(SHF_INPUT.DESCHGCT01(i) || SHF_INPUT.DESCHGST01(i))
else TEST.PMS_UTIL.STR_TO_DATE(SHF_INPUT.DESCHGDT01(i))
end),
-- below are fields that will be filled later
null , -- SOURCE_CALC ,
SHF_INPUT.OID(i) ,
null -- GAIN_CURR_DT_CALC
) ;
EXIT WHEN L_OHF%NOTFOUND; -- exit when last row is fetched
END LOOP;
COMMIT;
close L_OHF;
END;
end CONVERT_OHF_FA;
當您執行「SELECT INTO」時會產生什麼「扼流圈」?你是說這需要很長時間嗎?如果是這樣,查詢計劃是什麼? 「PMS_OHF」表中有多少行?有多少人擁有「OID」=「000052000」? 'oid'索引? –
另外,您是否已經追蹤了足夠的代碼,以便能夠確定在各種功能中花費了多少時間,與從源代碼讀取或寫入目標所花費的時間有多少?你的等待事件是什麼樣子的?你能利用並行性嗎? –
從看看縮小的示例,PL/SQL有特定需求嗎?任何原因你不能「插入/ * +追加* /進入new_table從old_table中選擇col1,col2,some_transform_function(col3),some_other_transform_function(col4);」這將是迄今爲止性能最好的解決方案。如果所有的轉換都可以在可以立即應用的功能上完成,那將是一條可行的路。 –