Oracle 데이터베이스에 대량 삽입:커서 루프와 단순 선택 중 어느 것이 더 좋습니까?
오라클 데이터베이스에 대량 삽입을 위한 더 나은 옵션은 무엇입니까? FOR Cursor 루프와 같은
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);
둘 중 하나가 더 나을 수 있는 구체적인 이유가 있습니까?
커서가 더 오래 걸리므로 Select(선택) 옵션을 권장합니다.
해야 하는 .
일반적으로 PL/SQL을 사용하는 대신 단일 SQL 문을 사용하여 이 작업을 수행할 수 있으면 수행해야 합니다.그것은 보통 더 효율적일 것입니다.
그러나 어떤 이유로 절차 논리를 더 추가해야 하는 경우 PL/SQL을 사용해야 할 수도 있지만, 행별 처리 대신 대량 작업을 사용해야 합니다. (참고: Oracle 10g 이상에서는 FOR 루프가 BULK COLLECT를 사용하여 한 번에 100개의 행을 가져오지만 여전히 행별로 삽입 문이 수행됩니다.)
예.
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 간의 컨텍스트 전환을 최소화하는 이점이 있습니다.또한 Oracle 11g은 레코드 테이블을 더 잘 지원하므로 각 열에 대해 별도의 PL/SQL 테이블을 가질 필요가 없습니다.
또한 데이터 볼륨이 매우 클 경우 데이터를 일괄 처리하도록 코드를 변경할 수 있습니다.
롤백 세그먼트/실행 취소 세그먼트가 트랜잭션 크기를 수용할 수 있는 경우 옵션 2가 더 좋습니다.옵션 1은 필요한 롤백 용량이 없고 큰 삽입을 작은 커밋으로 분할하여 롤백/실행 취소 세그먼트가 너무 작은 오류가 발생하지 않도록 해야 하는 경우에 유용합니다.
두 번째 옵션과 같은 간단한 삽입/선택이 훨씬 선호됩니다.첫 번째 옵션의 각 삽입에 대해 pl/sql에서 sql로 컨텍스트 전환이 필요합니다.trace/tkprof를 사용하여 각각 실행하고 결과를 검토합니다.
Michael이 언급했듯이 롤백이 문을 처리할 수 없는 경우 DBA가 추가 정보를 제공하도록 합니다.디스크는 저렴하지만 여러 패스에 데이터를 삽입하여 부분적으로 얻는 결과는 상당한 비용이 들 수 있습니다. (삽입과 관련된 실행 취소는 거의 없습니다.)
저는 이 질문에 한 가지 중요한 정보가 빠져 있다고 생각합니다.
몇 개의 레코드를 삽입하시겠습니까?
- 1에서 cca. 10.000까지라면 SQL 문을 사용해야 합니다(이해하기 쉽고 쓰기 쉽다고 말한 것처럼).
- cca. 10.000에서 cca. 100.000까지라면 커서를 사용해야 하지만 10.000 레코드마다 커밋할 논리를 추가해야 합니다.
- cca에서 100,000에서 수백만까지라면 더 나은 성능을 위해 대량 수집을 사용해야 합니다.
다른 답변을 읽어보면 알 수 있듯이, 사용 가능한 옵션이 많이 있습니다.만약 당신이 단지 10k 행 미만을 하고 있다면, 당신은 두 번째 옵션을 사용해야 합니다.
간단히 말해서, 약 10k 이상에 대해 <10k>라고 말할 수 있습니다.그것은 일종의 회색 지역입니다.많은 늙은 괴짜들이 큰 롤백 세그먼트에서 짖을 것입니다.하지만 솔직히 하드웨어와 소프트웨어는 코드를 몇 번만 실행하면 많은 레코드에 대한 옵션 2를 피할 수 있는 놀라운 발전을 이루었습니다.그렇지 않으면 1k-10k 행마다 커밋해야 합니다.여기 제가 사용하는 스니펫이 있습니다.저는 그것이 짧고 커서를 선언할 필요가 없기 때문에 좋습니다.또한 대량 수집 및 모두를 위한 이점도 있습니다.
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;
나는 오라클 사이트에서 옵션을 더 자세히 설명하는 링크를 찾았습니다.
사용할 수 있는 항목:
▁라고 불리는 FOR 과 함께 .Bulk binding
.
PL/ PL/SQL이forall
간단한 테이블 삽입의 경우 연산자 속도가 30배 더 빠릅니다.
BULK_COLLECT
오라클 및클FORALL
두 이두가특함알있습다니려져께은징지▁다▁as▁together있▁known니습▁these▁features▁two알려져라고 합니다.Bulk Binding
의 개별 PL/SQL PL/SQL을 사용하는 PL/입니다. 여기서 다중 개인이 아닌SELECT
,INSERT
,UPDATE
또는DELETE
명령문은 테이블에서 데이터를 검색하거나 테이블에 저장하기 위해 실행되며, 모든 작업은 한 번에 대량으로 수행됩니다.이렇게 하면 PL/SQL 엔진이 SQL 엔진으로 전달된 다음 PL/SQL 엔진으로 다시 전달되는 등 행에 한 번에 하나씩 개별적으로 액세스할 때 발생하는 컨텍스트 전환이 방지됩니다. with 대량수면려하행을딩INSERT
,UPDATE
,그리고.DELETE
PL 문, PL/SQL 문합니 안에 합니다.FORALL
진술.대량 바인딩을 수행하려면SELECT
진술, 당은포니다를 합니다.BULK COLLECT
절SELECT
설명신대를 사용하는 대신 INTO
.
성능을 향상시킵니다.
매일 전체 데이터를 다시 로드하는 작업은 수행하지 않습니다.예를 들어 덴버 사이트를 로드한다고 가정합니다.거의 실시간 델타를 위한 다른 전략이 있습니다.
테이블 생성 SQL을 사용합니다. 대량 로드와 거의 동일한 속도입니다. 예를 들어, 아래의 테이블 생성 문은 데이터를 준비하는 데 사용되어 열을 필요한 올바른 데이터 유형으로 캐스팅합니다.
CREATE TABLE sales_dataTemp 선택 주조(1열은 날짜로)는 SALES_QURARE로, (1열은 숫자로)는 SALES_IN_MILLIONS로 주조(.. 표 1에서)합니다.
이 임시 테이블은 사이트별로 분할된 내 대상 테이블의 구조를 정확히 반영합니다.그런 다음 DENVER 파티션과 파티션 스왑을 수행하면 새 데이터 세트가 생성됩니다.
언급URL : https://stackoverflow.com/questions/987013/bulk-insert-into-oracle-database-which-is-better-for-cursor-loop-or-a-simple-s
'itsource' 카테고리의 다른 글
.gitignore 파일에 Django 마이그레이션 파일을 추가해야 합니까? (0) | 2023.07.16 |
---|---|
장고의 CSRF 유효성 검사를 비활성화하는 방법은 무엇입니까? (0) | 2023.07.16 |
Ruby의 "continue"에 해당합니다. (0) | 2023.07.16 |
SQL Server에서 적용되는 인덱스 및 적용되는 쿼리란 무엇입니까? (0) | 2023.07.16 |
WooCommerce - 카트에 추가할 때 선택하지 않은 변형 무시 (0) | 2023.07.16 |