2013-11-21 44 views
5

我準備了一些fiddleOracle 11gR2:我可以使用DBMS_PARALLEL_EXECUTE運行我的自定義PL/SQL代碼嗎?

CREATE TABLE t_process 
    ("process_number" int, "process_status" varchar2(12)) 
; 

INSERT ALL 
    INTO t_process ("process_number", "process_status") 
     VALUES (1, 'PROCESSING') 
    INTO t_process ("process_number", "process_status") 
     VALUES (2, 'PROCESSING') 
    INTO t_process ("process_number", "process_status") 
     VALUES (3, 'TO_BE_KILLED') 
    INTO t_process ("process_number", "process_status") 
     VALUES (4, 'PROCESSING') 
    INTO t_process ("process_number", "process_status") 
     VALUES (5, 'PROCESSING') 
    INTO t_process ("process_number", "process_status") 
     VALUES (6, 'TO_BE_KILLED') 
    INTO t_process ("process_number", "process_status") 
     VALUES (7, 'TO_BE_KILLED') 
    INTO t_process ("process_number", "process_status") 
     VALUES (8, 'WAITING') 
    INTO t_process ("process_number", "process_status") 
     VALUES (9, 'KILLED') 
SELECT * FROM dual 
; 

這是我的處理過程:

CREATE OR REPLACE PROCEDURE MY_PROCEDURE(IN_ID IN NUMBER) IS 
BEGIN 
    UPDATE T_PROCESS SET process_status = 'KILLING' WHERE process_number = IN_ID; 
    COMMIT; 
    -- DO SOME STUFF 
    UPDATE T_PROCESS SET process_status = 'KILLED' WHERE process_number = IN_ID; 
    COMMIT; 
END MY_PROCEDURE; 

現在我想用DBMS_PARALLEL_EXECUTE運行此定製SQL

DECLARE 
    id1 number = :id1; 
    id2 number = :id2; 
BEGIN 
    MY_PROCEDURE(id1); 
END; 

所以,我的問題是:

我可以使用DBMS_PARALLEL_EXECUTE來執行上面的SQL語句嗎?

因爲我只發現了UPDATE的例子。也許CREATE_CHUNKS_BY_SQL只能選擇TO_BE_KILLED,然後RUN_TASK用上面的語句?

回答

3

是的,你可以很好地做到11g以上。我很驚訝爲什麼這裏沒有提到它。 START_ID,:

可以像begin MY_PROCEDURE(:start_id, :end_id); end;

您可能需要修改過程來接受兩個參數內run_task執行過程END_ID

下面是示例代碼(基於「create_chunks_by_rowid」)。

DECLARE 
    l_task  VARCHAR2(30) := 'parallel_processing'; 
    l_sql_stmt VARCHAR2(32767); 
    l_try  NUMBER; 
    l_status NUMBER; 
BEGIN 
    DBMS_PARALLEL_EXECUTE.create_task (task_name => l_task); 

    DBMS_PARALLEL_EXECUTE.create_chunks_by_rowid(task_name => l_task, 
               table_owner => 'SCHEMANAME', 
               table_name => 'T_PROCESS', 
               by_row  => TRUE, 
               chunk_size => 10000); 

    l_sql_stmt := 'begin MY_PROCEDURE(:start_id, :end_id); end;'; 

    DBMS_PARALLEL_EXECUTE.run_task(task_name  => l_task, 
           sql_stmt  => l_sql_stmt, 
           language_flag => DBMS_SQL.NATIVE, 
           parallel_level => 10); 

    -- If there is error, RESUME it for at most 2 times. 
    l_try := 0; 
    l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task); 
    WHILE(l_try < 2 and l_status != DBMS_PARALLEL_EXECUTE.FINISHED) 
    Loop 
    l_try := l_try + 1; 
    DBMS_PARALLEL_EXECUTE.resume_task(l_task); 
    l_status := DBMS_PARALLEL_EXECUTE.task_status(l_task); 
    END LOOP; 

    DBMS_PARALLEL_EXECUTE.drop_task(l_task); 
END; 
/

您可以通過以下方式create chunks以及根據您的具體情況/舒適。

CREATE_CHUNKS_BY_NUMBER_COL - 如果您想通過「process_number」

CREATE_CHUNKS_BY_SQL更新 - 如果你覺得BY_SQL將會給你一套非常小的塊進行處理。請注意,在這種方法中,每個塊只能處理每塊1行(start_id和end_id對於每個塊都是相同的)。

+0

還有一點,一個人不需要在自定義過程中提交,因爲DBMS_PARALLEL_EXECUTE.run_task會自動完成! – pahariayogi

3

沒有(或至少不是沒有真正的骯髒的黑客)。如果你想並行執行PL/SQL,我已經瞭解了以下選項:

  1. 使用dbms_job。您已經使用該許可證支付了許多費用,許多DBA都瞭解它,如果您沒有太高的監管,審計,安全或維護要求,它就會合理。你必須自己建立。它從1995年左右開始就已經出現了。
  2. 使用Redwood的Cronacle。這是我20年前的第一份工作,甜蜜的回憶。它使您可以使用Oracle類似的語法輕鬆地在集羣上運行作業,並且它比dbms_job更可靠,具有更好的日誌記錄並運行OS語句以及進行打印。但它花費你的錢。
  3. 使用不重要的調度程序。我目前在那裏工作,它與Cronacle類似,但是針對管理系統。當我無法輕鬆訪問操作系統,文件,特別是dbms_output等日誌記錄時,我討厭安排複雜的作業。
  4. 使用特定於應用程序的調度程序。例如,Oracle電子商務套件帶有一個很好的調度程序,具有安全性,相互排除,合理的日誌記錄等。如果您已經有了這樣的程序包,則它的使用通常是免費的,並且您的應用程序管理員有經驗。

當你是一名程序員,並且沒有標準,也不需要更多的並行處理時,你可以去dbms_job。當體積增加或功能要求更高時,請尋求更好的解決方案。

相關問題