SQL Server 데이터베이스에 많은 수의 큰 행을 삽입해야하는 Java 프로그램이 있습니다. 행의 수는 800k이고, 각 행의 크기는 약 200 바이트입니다.자바 스레드를 사용하여 데이터베이스에 병렬 삽입
현재는 일괄 처리로 50 개로 나누어 진 다음 각 일괄 처리가 하나의 명령문을 사용하여 삽입됩니다. (우리는 JTDS 로깅을 통해 각 배치에 대해 하나의 sp_exec 호출이 사용되었음을 확인했습니다.) 배치 크기를 25와 250 사이로 조정해도 큰 효과가없는 것 같고 50이 최적입니다.
나는 배치를 (말하자면) 5 개의 그룹으로 나누고 스레드를 사용하여 각 그룹을 병렬로 처리하는 방법을 실험했다. 이 속도는 상당히 빠릅니다. 5 스레드로 두 배 이상 빠릅니다.
제 질문은 스레드 사용을 강력하게 만드는 것입니다. 특히 일} 처리에 실패하면 예외가 _ 생합니다. 그 예외를 잡아서 호출자에게 넘기고 싶습니다. 다른 스레드가 끝내기 전에 (중단되었거나 완료되었는지) 100 % 확신하고 싶습니다. 나중에 프로그램에서 예외를 복구 할 때 예기치 않은 행이 테이블에 계속 도착하지 않기를 원하기 때문입니다.
는 여기에 내가 무슨 짓을했는지의 :
/** Method to insert a single batch. */
private void insertBatchPostings(Collection<Posting> postings) throws PostingUpdateException
{
// insert the batch using a single INSERT invokation
// throw a PostingUpdateException if anything goes wrong
}
private static final int insertionThreads = 5;
/** Method to insert a collection of batches in parallel, using the above. */
protected void insertBatchPostingsThreaded(Collection<Collection<Posting>> batches) throws PostingUpdateException
{
ExecutorService pool = Executors.newFixedThreadPool(insertionThreads);
Collection<Future> futures = new ArrayList<Future>(batches.size());
for (final Collection<Posting> batch : batches) {
Callable c = new Callable() {
public Object call() throws PostingUpdateException {
insertBatchPostings(batch);
return null;
}
};
/* So we submit each batch to the pool, and keep a note of its Future so we can check it later. */
futures.add(pool.submit(c));
}
/* Pool is running, indicate that no further work will be submitted to it. */
pool.shutdown();
/* Check all the futures for problems. */
for (Future f : futures) {
try {
f.get();
} catch (InterruptedException ex) {
throw new PostingUpdateException("Interrupted while processing insert results: " + ex.getMessage(), ex);
} catch (ExecutionException ex) {
pool.shutdownNow();
throw (PostingUpdateException) ex.getCause();
}
}
}
이 나는 모든 스레드가 휴면 보장 할 반환 무렵.
질문
은 (내가 부탁 해요 정확히 명확히하기 위해 노력하고있어.)
- 위의 코드가 완전히 견고, 그 어떤 스레드 삽입에
insertBatchPostingsThreaded
후 계속 작동 보고? - Java 동시성 기능을 사용하여보다 효율적이고 간편하게 사용할 수있는 방법이 있습니까? 내 코드는 나에게 너무 복잡해 보입니다 (가장자리가없는 경우 의혹을 제기 함).
- 하나의 스레드가 실패하자마자 실패하게하는 가장 좋은 방법은 무엇입니까?
나는 자연적인 자바 프로그래머가 아니기 때문에 나는 그 사실을 광고하지 않는 무언가로 끝나기를 바라고있다. :)
아우. 코드를 읽기 쉽도록 generics를 사용할 수 있습니까? –
배치 삽입에 대한 @Edmund 테이블 인덱스를 비활성화하면 속도가 향상됩니다. 인덱스 재 계산을 트리거해야합니다. – hidralisk
@ 루이스 (Loois) - 정확하게 작동하는지 확인하기 위해 작업 프로그램에서 축 어적으로 복사했습니다. 기존 앱입니다. 그러나 나는 그것을 현대 자바로 번역하려고 시도했다. for 루프가 당신에게 가장 불쾌감을 준다고 추측하지만 컬렉션 유형도 변환했습니다. – Edmund