2008-11-13 4 views
4

iBatis를 사용하여 하나의 테이블 (SQL Server 2005)에 20,000 개의 행을 삽입해야합니다. 가장 빠른 방법은 무엇입니까? 난 이미 배치 모드를 사용하고 있지만, 많은 도움이되지 않았다 :IBATIS를 사용하여 INSERT를 수행하는 가장 빠른 방법

try { 
    sqlMap.startTransaction(); 
    sqlMap.startBatch(); 
    // ... execute statements in between 
    sqlMap.commitTransaction(); 
} finally { 
    sqlMap.endTransaction(); 
} 

답변

1

대량 삽입 최상의 데이터베이스에 자신의 일괄 로더 도구를 사용하여 수행됩니다. 오라클의 경우 SQL * Loader입니다. 종종 이것은 당신이 쓸 수있는 것보다 빠릅니다.

2

DB 서버에만 해당되는 것은 아니지만 이전에 csv 형식의 로컬 파일에 행을 쓰고 데이터베이스에서 파일을 가져 오는 데 성공했습니다. 이는 insert 문이나 배치 삽입보다 훨씬 빠릅니다.

+0

은 최근에 MySQL과 같은 경험을했습니다. 파일에서로드 된 일반 INSERT INTO 문을 사용하여 데이터를 삽입하는 것은 위의 설명과 같이 배치 삽입을 수행하는 것보다 훨씬 빠릅니다. –

2

SQL Server에서 레코드를 일괄 적으로 삽입하는 방법은 BULK INSERT입니다. 그러나이 메서드는 레코드를 응용 프로그램에서 직접 가져 오지 않고 텍스트 파일에서로드합니다.

또한 파일을 만드는 데 소요 된 시간도 고려하지 않습니다. 실제 삽입물의 속도를 상쇄하면 무게를 측정해야 할 수도 있습니다. 전반적으로 조금 느리지 만 데이터베이스 서버를 더 짧은 시간에 묶어야합니다.

당신이 시도 할 수있는 유일한 다른 방법은 인덱스를 전혀 사용하지 않고 완전히 다른 테이블에 배치를 삽입 (스테이징)하는 것입니다. 그런 다음 해당 스테이징 테이블에서 목표 테이블로 레코드를 이동하고 스테이징 테이블을 제거하십시오. 이렇게하면 데이터를 서버로 먼저 이동하므로 최종 삽입이 모두 SQL Server 자체에서 발생할 수 있습니다. 그러나 다시 : 두 단계 프로세스이므로 두 단계의 시간을 계산해야합니다.

+1

파일에서 대량로드. 플랫 파일을 작성하는 것은 대개 매우 빠릅니다. –

4

다른 사람이 말하는 대량 로더를 제외하고 SQL을 통해 최상의 수행 방법을 고려해 봅시다. (그리고 혼합 된 데이터를 다른 테이블로 전송하는 경우 벌크 로더가 제대로 작동하지 않습니다.)

우선, 사용중인 추상화 레이어 (이 경우 iBatis)를 효과적으로 사용해서는 안됩니다 당신에게 작은 가치를 제공 할 것이지만, 그 추상화 계층은 일부 (꼭 그렇지는 않지만 일부) CPU 비용을 가질 것입니다. 정말로 원시 데이터베이스 연결 만 사용하면됩니다.

다음으로 INSERT 명령문을 보내 게됩니다. 문제는 INSERT INTO TABLE1 VALUES ('x', 'y', 12)와 준비된 명령문 (INSERT INTO TABLE1 VALUES (?,?,?))에 대해 간단한 문자열을 사용해야하는지 여부입니다.

데이터베이스 및 DB 드라이버에 따라 다릅니다.

간단한 문자열 사용과 관련된 문제는 기본적으로 내부 형식 (자바 데이터를 삽입한다고 가정)에서 문자열로 변환하는 비용입니다. 숫자 나 날짜를 String으로 변환하는 것은 실제로는 상당히 비싼 CPU 작업입니다. 일부 데이터베이스 및 드라이버는 단순히 문자열 데이터가 아닌 이진 데이터로 직접 작동합니다. 따라서이 경우 PreparedStatement는 잠재적으로 데이터를 변환 할 필요가없는 일부 CPU 절약을 얻을 수 있습니다.

이 요소는 DB 공급 업체 및 잠재적으로 JDBC 공급 업체에 따라 다를 수 있다는 단점이 있습니다. 예를 들어, Postgres (저는 믿습니다)는 바이너리가 아닌 SQL 문자열로만 작동하므로 PreparedStatement를 사용하는 것은 단순히 문자열을 직접 만드는 것 이상의 낭비입니다.

다음으로, 명령문 유형을 지정하면 JDBC Statement 클래스의 addBatch() 메소드를 사용하려고합니다. addBatch는 SQL 문을 그룹화하여 일괄 처리합니다. 이점은 DB에 여러 요청을 전송하는 대신 단일 LARGE 요청을 전송한다는 것입니다. 이렇게하면 네트워크 트래픽이 줄어들어 처리량이 눈에 띄게 향상됩니다.

세부 사항은 모든 드라이버/데이터베이스가 addBatch (적어도 좋지는 않음)를 지원하지는 않지만 배치의 크기가 제한된다는 것입니다. 대부분의 경우 20,000 개의 행 모두에 대해 addBatch를 수행 할 수는 없지만 최선의 방법이 될 수는 있습니다. 이 제한은 또한 데이터베이스에 따라 다를 수 있습니다.

오라클의 경우 이전에는 64K 버퍼를 사용했습니다. 기본적으로 리터럴 INSERT 문을 사용하는 래퍼 함수를 ​​작성하고이를 64K 배치로 축적합니다.

그래서 JDBC를 통해 SQL을 통해 데이터를 대량 삽입하려는 경우이를 수행하는 방법이 있습니다. 가장 큰 개선은 일괄 처리 모드입니다. Statement와 PreparedStatement는 드라이버가 바이너리 프로토콜을 지원할 경우 잠재적으로 CPU를 절약하고 네트워크 트래픽을 줄일 수 있습니다.

충분히 만족할 때까지 테스트, 린스 및 반복하십시오.