2009-07-02 2 views
4

나는 로그 파일을 분석하고 방대한 양의 데이터를 데이터베이스에 삽입하는 응용 프로그램을 가지고있다. Java로 작성되었으며 JDBC를 통해 MySQL 데이터베이스와 통신합니다. 필자는 특정 유스 케이스에서 가장 빠른 데이터를 찾기 위해 여러 가지 방법을 실험했습니다. 현재 최고의 공연이 될 것 같다 하나는 다음과 같이 확장 삽입 (여러 행 예를 들어, 하나의 삽입)를 발행하는 것입니다문자열을 작성하지 않고 JDBC를 사용하여 확장 삽입을 수행하는 방법은 무엇입니까?

INSERT INTO the_table (col1, col2, ..., colN) VALUES 
(v1, v2, v3, ..., vN), 
(v1, v2, v3, ..., vN), 
..., 
(v1, v2, v3, ..., vN); 

행의 수는 수만이 될 수 있습니다.

나는 준비된 문장을 사용해 보았지만 아무런 차이가 없었습니다. 왜냐하면 각 삽입물이 여전히 DB에 개별적으로 보내졌고 테이블을 잠궈 둘 필요가 있기 때문입니다. 내 앞에있는 코드에서 일한 동료는 일괄 처리를 사용해 보았지만 성능이 좋지 않았습니다.

확장 삽입을 사용한다는 것은 SQL 문자열을 직접 작성해야한다는 것을 의미합니다 (행 수가 가변적이기 때문에). 모든 종류의 SQL 주입 벡터를 열 수 있다는 것을 의미합니다. 나는 내 자신을 발견 할 정도로 지능이 없습니다. 이렇게하는 더 좋은 방법이 있어야합니다.

분명히 내가 삽입 한 문자열을 제외하고는 단지 str.replace("\"", "\\\""); (', ?, \에 대해 반복)과 같은 것으로 만 이스케이프하지만 분명히 충분하지 않을 것이라고 확신합니다. + 일괄 삽입

답변

4

준비된 문 :

PreparedStatement stmt = con.prepareStatement(
"INSERT INTO employees VALUES (?, ?)"); 

stmt.setInt(1, 101); 
stmt.setString(2, "Paolo Rossi"); 
stmt.addBatch(); 

stmt.setInt(1, 102); 
stmt.setString(2, "Franco Bianchi"); 
stmt.addBatch(); 

// as many as you want 
stmt.executeBatch(); 
+0

하나의 삽입 물 또는 여러 물을 발행합니까? 또는 배치 작업을 통해 많은 준비된 명령문을 발행하는 간접비가 없어지 는가? – Theo

+0

일괄 처리는 준비된 명령문의 오버 헤드를 최소화해야합니다 – dfa

+0

+1 실제 코드 –

1

나는 당신의 삽입을 일괄 처리 시도하고 그 수행 방법을 볼 것이다.

일괄 처리에 대한 자세한 내용은이 (http://www.onjava.com/pub/a/onjava/excerpt/javaentnut_2/index3.html?page=2)을 읽으십시오.

+0

일괄 처리는 솔루션 인 것처럼 보이지만 이전에 제 코드에서 작업 한 제 동료에 따르면 비교하지 않습니다 확장 인서트 사용 (이 질문을 포함하도록 수정했습니다). – Theo

+0

동료가이 삽입을 일괄 처리하려했으나 배치를 사용하는 것이 삽입하려는 모든 데이터를 반복하는 것만 큼 간단하지 않고 하나의 큰 일괄 처리에 모두 추가하고 executeBatch를 호출하는 것만 큼 간단하지 않습니다. 다음은 일괄 처리에 관한 MySQL 메일 링리스트 (http://lists.mysql.com/maxdb/14236)의 게시물입니다. 설명했다면 executeBatch를 두 번 이상 호출하고 싶을 것이다. –

+0

비록 배치 연산이 확실히 다시 시도해 볼 가치가있는 것처럼 보이지만, 그가 말하는 것이 사실이라면 (그리고 코드를 절대 사용하지 않고 그냥 시도해 버린 것처럼 보입니다) 확장 된 삽입과 일괄 처리 사이의 성능에는 큰 차이가 있습니다. 나는 그것이 모두 병목이 어디로 내려 왔는지 추측합니다 : 느린 데이터베이스에 데이터를 보내는 것인가, 아니면 문제가되는 데이터베이스 내부의 모든 것을 잠그고 잠그는 것입니까? 후자의 일괄 처리가 문제를 해결하지 못한다면, 이전의 일괄 처리가 제대로 수행 될 수 있고 보안이 강화됩니다. – Theo

1

수만 건의 레코드를로드하는 경우 대량로드를 사용하는 것이 좋습니다. 나는 그것이 MySQL의가에서보다 열을 많이 삽입 많이 긴 시간을 내 코드를했다 눈치 때문에 확장 삽입 및 배치 단일 삽입의 차이에 관한

http://dev.mysql.com/doc/refman/5.0/en/load-data.html

+0

-1 벌크 로더는 정적 데이터가있는 경우에만 유용합니다 – dfa

+0

@dfa - 정적 데이터 란 무엇입니까? – pjp

+1

나는 그것이 충분히 공정한 제안이라고 생각한다. CSV 파일을 작성하고 LOAD DATA INFILE을 사용하는 것은 내 경험으로는 정말 빠를 수 있습니다. 그것은 CSV 파일을 작성하고 MySQL이 찾을 수 있도록하기 때문에 조금 더 복잡합니다. – Theo

1

, 그 이유는 내가 확장 삽입을 사용하는 것입니다 결정 단말기. 이것은 5000의 일괄 처리로 인서트를 일괄 처리하는 경우에도 마찬가지였습니다. 결국 솔루션은 확장 된 인서트를 사용하는 것이 었습니다.

나는이 이론을 빨리 재검토했다.

나는 120 만 행의 테이블을 두 번 덤프했습니다. 당신이 mysqldump를 함께 얻을 기본 확장 삽입 문 및 사용하여 다른를 사용하여 하나 :

mysqldump --skip-extended-insert 

그때 나는 단순히 새로운 테이블로 다시 파일을 수입하고 시간이 초과되었습니다.

확장 삽입 테스트는 1m35s에서 완료되고 다른 테스트는 3m49s에서 완료됩니다.

+0

그래도 준비된 진술은 고려하지 않습니다. 공정한 비교를 위해 먼저 INSERT 문을 준비한 응용 프로그램에 데이터를로드하고 각 행을 일괄 처리에 추가 한 다음 실행해야합니다. 나는 여전히 당신이 최종이라고 생각하지만, 준비된 진술과 배치가 확장 된 삽입만큼 빠르면 실제로 말하지 않습니다. – Theo

관련 문제