2012-11-08 1 views
2

나는 사악한 문제가있다.다른 테이블과 뷰에서 삭제/삽입하는 방법

proc_log('DELETE 1'); 
DELETE FROM table_1; 
proc_log('INSERT 1'); 
INSERT INTO table_1 SELECT * FROM view_1; 
proc_log('FINISH 1'); 

그리고보기/표 2, 3, 4, 5와 같은 ... 그리고 36

를 : 오라클 10에서 또 다시 그런 일이 끝난 수행 뷰와 테이블의 쌍과가있다

PROCEDURE proc_import(p_table VARCHAR2) IS 
BEGIN 
    proc_log('DELETE ' || p_table); 
    EXECUTE IMMEDIATE 'DELETE FROM table_' || p_table; 
    proc_log('INSERT ' || p_table); 
    EXECUTE IMMEDIATE 'INSERT INTO table_' || p_table || ' SELECT * FROM view_' || p_table; 
    proc_log('FINISH || p_table); 
    COMMIT; 
END; 

을 그리고 모든 36쌍의 함수를 호출 :

나는 같은 것을 할 싶습니다.

놀랍지 않게도이 항목은 하드 코딩 된 것보다 약 50 % 느립니다.

내 질문 : 누구보다 빨리 만드는 방법에 대한 아이디어가 있습니까? 또는 더 좋게, 나는이 재료를 어떻게 다르게 그러나 유사하게 우아하게 할 수 있습니까?


편집

전체 물건이 같이 내장되어 있습니다 : 프로 시저 proc_import 한 번 밤 작업에 의해 불려

CREATE OR REPLACE PACKAGE PKG_IMPORT IS 
    PROCEDURE proc_log IS BEGIN [funky not important stuff] END; 

    PROCEDURE proc_import IS 
    BEGIN 
     proc_import_table('1', TRUE); 
     proc_import_table('2'); 
     proc_import_table('3'); 
     proc_import_table('4', TRUE); 
     proc_import_table('5'); 
     ... 
     proc_import_table('36'); 
    END; 

    PROCEDURE proc_import(p_table VARCHAR2, p_whole BOOLEAN DEFAULT FALSE) IS 
    BEGIN 
    proc_log('DELETE ' || p_table); 
    IF p_whole THEN 
     EXECUTE IMMEDIATE 'DELETE FROM table_' || p_table; 
    ELSE 
     EXECUTE IMMEDIATE 'DELETE FROM table_' || p_table || ' WHERE business_logic_applies'; 
    END IF; 
    proc_log('INSERT ' || p_table); 
    EXECUTE IMMEDIATE 'INSERT INTO table_' || p_table || ' SELECT * FROM view_' || p_table; 
    proc_log('FINISH || p_table); 
    COMMIT; 
    END; 
END PKG_IMPORT; 

. 모든 proc_import_table 호출이 하드 코딩 된 이유는 일부 테이블에 추가 가져 오기 정보가 필요하기 때문입니다.

내가 할 수 있는지 알 수 없기 때문에 여기에 원본 코드를 복사하거나 붙여 넣을 수 없습니다. 희망 ...

+1

전체로 작성하십시오. 여전히'proc_import'를 36 번 호출해야합니다. 이것은 귀하의 질문에 대한 답변이 아니지만 마치 데이터베이스의 구조에 문제가있는 것처럼 들립니다. – Ben

+0

여기 뭔가가 제대로 보이지 않습니다. 야간 작업이고 도움말 성능을 잘라내거나 추가하는 경우 실행하는 데 몇 초 이상 걸리는 것으로 가정합니다. 그러나 실행하는 데 몇 초 이상 걸리면 동적 SQL을 몇 번 사용하는 오버 헤드로 인한 차이를 느끼지 않아야합니다. 어쩌면 테스트를 몇 번 더 실행해야 할 것입니다. 아마도 다른 요인이 성능 차이를 야기했을 것입니다. –

답변

2

우선, 삭제할 행에 대한 조건이 없으면 테이블을자를 수 있습니다.

TRUNCATE TABLE table_1; 

TRUNCATE

은 DDL 작업이며이 phsically 행을 삭제하지 않습니다, 그것은 매우 빠르게 작업을하고, 워터 마크 (water mark)를 조작합니다. 또한 DDL이기 때문에 롤백 할 수 없다는 것을에 명심하십시오.

반면에 일반 경로 삽입 대신 직접 경로 삽입을 수행 할 수 있습니다. 이것을 시도하십시오 :

INSERT /*+ append */ into table_1 select * from view_1; 

이렇게하면 오라클이 높은 워터 마크 바로 위에 데이터를 쓰게되므로 작업 속도가 빨라집니다. 테이블이 PARALLEL 인 경우도 도움이됩니다.

+0

나는 보통 'TRUNCATE'도 선호하지만, 말했듯이 "롤백 가능"하지 않습니다. 우리는 뭔가 잘못되었을 때 emtpy 테이블을 갖고 싶지 않습니다. 이 직접적인 경로는 매우 흥미 롭습니다. 정확하게 무엇을하는지 약간의 연구를 해보겠습니다. 감사. – Joshua

0

오라클이 '즉시 실행'으로 할 수없는 쿼리를 사전 컴파일 할 수 있으므로 원본 코드가 더 빨리 실행됩니다.

새 코드가 더 간결 해 보이지만 실제로는 읽기가 훨씬 어렵습니다. 적어도 테이블 번호를 전달하기보다는 전체 테이블 이름을 지정해야합니다. 그렇지 않으면 코드를 보는 다른 사람이 숫자의 의미를 알아 내야합니다.

즉, 나는 36 개의 delete 문과 36 개의 insert 문을 선호한다고 생각합니다. 훨씬 덜 복잡하고 훨씬 정돈되어 있습니다. 짧은 문장으로 도울 수 있다면 모든 문장을 자신의 문장으로 옮길 수 있습니다.

+0

정상적인 상황에서 나는 귀하의 의견에 완전히 동의합니다. 그러나이 경우에는 좀 더 복잡합니다. 예를 들어 "DELETE/INSERT"작업의 순서가 매우 중요합니다. 짧은 프로 시저 호출을 사용하면 변경하고 추적하는 것이 훨씬 쉽습니다. 또한 나는 Java Dev이기 때문에 기능을 캡슐화하는 것이 내 일이다;) – Joshua

+0

나는 java 개발자이기도하다. 순서가 중요한 경우, 정확한 순서로 문장을 작성하십시오. 좋은 코드 디자인의 원칙은 모든 것을 짧은 공간으로 압축해야한다는 것을 의미하지는 않습니다. 가독성/유지 관리 가능성도 똑같이 중요합니다. 그것은 당신의 코드입니다,하지만 그것을 유지해야한다면 나는 행복하지 않을 것입니다! – DaveRlz

관련 문제