복붙노트

[SQL] 더 : FOR 커서 루프 또는 간단한 선택 오라클 데이터베이스에 대량 삽입?

SQL

더 : FOR 커서 루프 또는 간단한 선택 오라클 데이터베이스에 대량 삽입?

어느 Oracle 데이터베이스에 대량 삽입을위한 더 나은 옵션이 될 것인가? 같은 FOR 커서 루프

DECLARE
   CURSOR C1 IS SELECT * FROM FOO;
BEGIN
   FOR C1_REC IN C1 LOOP
   INSERT INTO BAR(A,
                B,
                C)
          VALUES(C1.A,
                 C1.B,
                 C1.C);
   END LOOP;
END

또는 간단한은, 같은 선택 :

INSERT INTO BAR(A,
                B,
                C)
        (SELECT A,
                B,
                C
        FROM FOO);

특정 이유는 둘 중 하나가 더 나은 것입니까?

해결법

  1. ==============================

    1.커서가 더 오래 걸릴 때문에 선택 옵션을 추천 할 것입니다. 또한, 선택은 당신의 쿼리를 수정하는 누군가를 위해 이해하기 훨씬 쉽게되어 사용

    커서가 더 오래 걸릴 때문에 선택 옵션을 추천 할 것입니다. 또한, 선택은 당신의 쿼리를 수정하는 누군가를 위해 이해하기 훨씬 쉽게되어 사용

  2. ==============================

    2.단일 SQL 문을 사용하는 대신, 당신이해야 PL / SQL을 사용하여 할 수 있다면 일반적인 경험 법칙이다. 그것은 일반적으로 더 효율적입니다.

    단일 SQL 문을 사용하는 대신, 당신이해야 PL / SQL을 사용하여 할 수 있다면 일반적인 경험 법칙이다. 그것은 일반적으로 더 효율적입니다.

    당신은 (어떤 이유로)보다 절차 적 로직을 추가해야하는 경우, 당신은 PL / SQL을 사용해야 할 수도 있습니다,하지만 당신은 행 단위 처리 대신 대량 작업을 사용해야합니다. (참고 : 오라클 10g 이상에서, 당신을위한 루프가 자동으로 한 번에 100 개의 행을 가져 COLLECT BULK를 사용하지만 사용자 삽입 문이 아직 완료 행에 의해 행됩니다).

    EG

    DECLARE
       TYPE tA IS TABLE OF FOO.A%TYPE INDEX BY PLS_INTEGER;
       TYPE tB IS TABLE OF FOO.B%TYPE INDEX BY PLS_INTEGER;
       TYPE tC IS TABLE OF FOO.C%TYPE INDEX BY PLS_INTEGER;
       rA tA;
       rB tB;
       rC tC;
    BEGIN
       SELECT * BULK COLLECT INTO rA, rB, rC FROM FOO;
       -- (do some procedural logic on the data?)
       FORALL i IN rA.FIRST..rA.LAST
          INSERT INTO BAR(A,
                          B,
                          C)
          VALUES(rA(i),
                 rB(i),
                 rC(i));
    END;
    

    위에서 언급 한 콘텍스트를 최소화하는 이점이 SQL 및 PL / SQL를 전환 갖는다. 오라클 11g는 또한 각 열에 대해 별도의 PL / SQL 테이블이 필요가 없습니다 그래서 기록의 테이블에 대한 더 나은 지원을하고있다.

    데이터의 양이 매우 큰 경우 또한, 일괄 적으로 데이터를 처리하는 코드를 변경할 수 있습니다.

  3. ==============================

    3.롤백 세그먼트 / 실행 취소 세그먼트는 트랜잭션의 크기를 수용 할 수있는 경우 다음 옵션이 더 낫다. 당신이 필요로하는 롤백 능력이 있고 롤백 / 실행 취소 세그먼트 너무 작은 에러가 발생하지 않도록 작은 커밋에 큰 삽입을 깰이없는 경우 옵션 1에 유용합니다.

    롤백 세그먼트 / 실행 취소 세그먼트는 트랜잭션의 크기를 수용 할 수있는 경우 다음 옵션이 더 낫다. 당신이 필요로하는 롤백 능력이 있고 롤백 / 실행 취소 세그먼트 너무 작은 에러가 발생하지 않도록 작은 커밋에 큰 삽입을 깰이없는 경우 옵션 1에 유용합니다.

  4. ==============================

    4.당신의 두번째 옵션이 훨씬 바람직하다 같은 간단한 인서트 / 선택합니다. 1 옵션에서 각 삽입을 위해 당신은 PL / SQL을 SQL에서 컨텍스트 스위치가 필요합니다. 추적 / TKPROF 각을 ​​실행하고 결과를 검토합니다.

    당신의 두번째 옵션이 훨씬 바람직하다 같은 간단한 인서트 / 선택합니다. 1 옵션에서 각 삽입을 위해 당신은 PL / SQL을 SQL에서 컨텍스트 스위치가 필요합니다. 추적 / TKPROF 각을 ​​실행하고 결과를 검토합니다.

    마이클 언급으로, 롤백 명령문을 처리 할 수 ​​없습니다, 경우 다음 DBA는 더 당신을 줄 수 있습니다. 다중 패스에 데이터를 삽입에서 오는 부분적인 결과는 잠재적으로 매우 비싼 반면 디스크, 저렴합니다. (거의 취소 삽입과이 연결되지 않습니다.)

  5. ==============================

    5.이 질문에 하나 개의 중요한 정보가 누락되어 있다고 생각합니다.

    이 질문에 하나 개의 중요한 정보가 누락되어 있다고 생각합니다.

    당신은 얼마나 많은 레코드를 삽입 할 것인가?

  6. ==============================

    6.당신이 다른 답변을 읽어 볼 수 있듯이, 사용할 수있는 옵션이 많이 있습니다. 그냥 <10,000 행을하고 있다면 당신은 두 번째 옵션으로 가야한다.

    당신이 다른 답변을 읽어 볼 수 있듯이, 사용할 수있는 옵션이 많이 있습니다. 그냥 <10,000 행을하고 있다면 당신은 두 번째 옵션으로 가야한다.

    즉, 약> 10,000 모든 방법에 대해 <100,000 대답. 그것은 회색 영역의 종류이다. 오래된 괴짜의 많은 큰 롤백 세그먼트에서 껍질 것입니다. 그러나 정직하게 하드웨어와 소프트웨어를 사용하면 코드 만 몇 번을 실행하면 당신이 기록의 많은에 대한 옵션이 멀리 얻을 수있을 수있는 위치에 놀라운 진전을 만들었습니다. 그렇지 않으면 당신은 아마 모든 1K-10K 또는 행 그래서를 저지해야한다. 여기 내가 사용하는 조각이다. 좋아 나는 그 짧은 내가 커서를 선언 할 필요가 없기 때문에. 게다가 그것은 수집 및 FORALL 대량의 장점을 가지고있다.

    begin
        for r in (select rownum rn, t.* from foo t) loop
            insert into bar (A,B,C) values (r.A,r.B,r.C);
            if mod(rn,1000)=0 then
                commit;
            end if;
        end;
        commit;
    end;
    

    좀 더 자세히 옵션을 보여 오라클 사이트에서이 링크를 발견했다.

  7. ==============================

    7.당신이 사용할 수있는:

    당신이 사용할 수있는:

    바인딩 대량이라고 수집 FOR ALL과 함께 대량.

    PL / SQL FORALL 운영자는 빠른 간단한 테이블 삽입에 대한 30 배 속도 때문입니다.

    BULK_COLLECT 및 Oracle FORALL이 두 가지 기능은 벌크 바인딩으로 알려져있다. 벌크 귀속 모든 작업은 대량으로, 한 번에 수행, 테이블에서의 UPDATE 또는 DELETE 문에서 검색을 실행하는 대신 여러 개의 개별 SELECT, INSERT,의, PL / SQL 기술, 또는 데이터를 저장합니다. 이 컨텍스트를 전환 방지 한 번에 할 때 개별적으로 접근 행 하나 인 PL / SQL 엔진이 등 뒤로 PL / SQL 엔진에 다음의 SQL 엔진에 이상 통과해야하고, 경우에 당신이 얻을. INSERT, UPDATE 및 DELETE 문으로 벌크 바인딩을 수행하려면, 당신은 PL / SQL FORALL 문 내에서 SQL 문을 묶습니다. SELECT 문으로 벌크 바인딩을 수행하려면, 대신 INTO를 사용하는 SELECT 문에서 BULK COLLECT 절을 포함한다.

    그것은 성능을 향상시킵니다.

  8. ==============================

    8.나는 데이터의 일일 완전한 재 장전을 위해 둘 다 할 수 없습니다. 예를 들어 내 덴버 사이트를 로딩하고 말한다. 거의 실시간 델타 다른 전략이있다.

    나는 데이터의 일일 완전한 재 장전을 위해 둘 다 할 수 없습니다. 예를 들어 내 덴버 사이트를 로딩하고 말한다. 거의 실시간 델타 다른 전략이있다.

    나는이 대량로드처럼 거의 빨리 내가 ​​찾은으로 테이블 SQL을 만들어 사용 A는 CREATE TABLE 문 아래 예를 들어, 필요한 올바른 데이터 형식으로 열을 주조, 데이터를 준비하는 데 사용됩니다 :

    표 sales_dataTemp 선택 등을 CREATE SALES_QUARTER로 주조 (날짜로 1 열) SALES_IN_MILLIONS로 주조 (번호 등 판매) .... 에서 1 번 테이블;

    이 임시 테이블 거울 내 목표 테이블의 구조는 정확히 사이트에서 분할 된 목록이다. 그때 덴버 파티션과 파티션 스왑을하고 나는 새로운 데이터 세트가 있습니다.

  9. from https://stackoverflow.com/questions/987013/bulk-insert-into-oracle-database-which-is-better-for-cursor-loop-or-a-simple-s by cc-by-sa and MIT license