2014-01-12 2 views
1

내 Java 응용 프로그램에서 하드 디스크에 큰 테이블을 저장해야하므로 영구적으로 저장해야합니다.배열을 SQLite-Databse에 배열로 저장

내 첫 번째 시도는 다음과 같이이었다 : 은 (내가 & J 300.000과 이상으로 올라갈 수 있습니다, 그래서 300.000^2 번 항목의 배열, 충돌 내 시스템을 가지고있다.)

stmt.executeUpdate("DROP TABLE IF EXISTS calculations;"); 
stmt.executeUpdate("CREATE TABLE calculations (factorA, factorB, result);"); 
double temp = 0; 
for (i = 0; i < datasource.size(); i++) { 
    for (int j = 0; j < datasource.size(); j++) { 
     if (i != j) { 
      temp = calc(datasource.get(i),datasource.get(j)); 
      stmt.execute("INSERT INTO calculations (factorA, factorB, result) VALUES ('"+i+"','"+j+"','"+temp+"')"); 
     } 
    } 
} 

이제 이것은 문자열 인 SQL 명령 때문에 극단적 인 느린 작업을 수행합니다.

내 새로운 추측은 아마도 10.000 i의 결과를 먼저 계산 한 다음 그 결과를 한 단위로 저장하는 것이 좋습니다. 데이터 베이스.

하지만 구현하기 전에 누구에게 더 좋은 아이디어가 있습니까? 데이터베이스 사용은 필수적인 것은 아니며 쉽게 액세스하고 구현하기가 쉽습니다.

감사합니다.

+0

대량 삽입을 트랜잭션으로 수행해야합니다. https://www.sqlite.org/lang_transaction.html - SQLite 엔진에서 이들을 큐에 넣고 트랜잭션이 완료되었다고 표시하면 하나씩 처리하는 대신 번개를 빨리 처리합니다. –

+0

빠른 쓰기 또는 빠른 읽기가 필요합니까? 얼마나 많은 행을 추출할까요? factorA + factorB의 구성이 색인으로 사용 가능합니까? – elbuild

+0

사실 나는 빠른 쓰기와 읽기가 모두 필요하지만 처음에는 글쓰기가 필요합니다. – goetzmoritz

답변

1

Transaction (예 : 실패는 문제가되지 않는다고 가정합니다. 예를 들어, 일부 행을 삽입하지 못한 경우 이전 행을 롤백하지 않고 계속 진행할 수 있음)의 모든 행을 n 또는 내부에 추가하십시오. 외부 루프에서

int n = 1000; //commit every 1000 rows, or you can tweak 
int count = 0; //counter for rows inserted 

시작 트랜잭션하십시오 루프 oustide입니다 카운터를 선언 . 증가 및 내부 루프 카운터를 확인

if(count % n == 0){ 
    //commit the transaction 
} 
count++ 

I는 열 및 I의 수를 감소

http://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html

+0

고마워, 이건 내가 지금하고있는 일이야. 하지만 여전히 독서는 상당히 느립니다. 난 그냥, 당신이 정말로 큰 테이블에 액세스 할 필요가있을 때, SQLite는 갈 길이 멀다고 생각합니다. 하지만 또 뭐야?! – goetzmoritz

+0

쿼리가 느려지고 SQL IDE에서 직접 실행 해 보셨습니까? 페이지 매김을 시도하고, 모든 행을 읽고/쓰며, 메모리가 효율적입니다. – isah

1
 int BLOCK_SIZE = 15000; 
     stmt.executeUpdate("DROP TABLE IF EXISTS calculations;"); 
     stmt.executeUpdate("CREATE TABLE calculations (factor_idx text NOT NULL PRIMARY KEY,result text NOT NULL);"); 
     double temp = 0; 
     int block_ctr = 1; 
     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < datasource.size; i++) { 
      for (int j = 0; j < datasource.size; j++) { 
       if (i != j) { 
        temp = calc(a, b); 
        // init the statement when counter = 1 
        if (block_ctr == 1) { 
         sb.append("INSERT INTO 'calculations' SELECT '" + i + "_" + j + "' AS 'factor_idx', '" + temp + "' AS 'result'"); 
        } 


        // then commit only every BLOCK_SIZE blocks 
        if (block_ctr <= BLOCK_SIZE) { 
         sb.append("UNION SELECT '" + i + "_" + j + "','" + temp + "'"); 
        } else { 
         stmt.execute(sb.toString()); 
         sb.setLength(0); // better then creating a new sb 
         block_ctr = 0; 
        } 
        block_ctr++; 
       } 
      } 
     } 

(말자는 외부 루프에 다시 거래를 재개하는 것을 잊지) StringBuilder를 사용하여 작성된 명령문을 작성했습니다. 훨씬 빠르며 i와 j를 연결하는 기본 키 열의 색인을 사용하여 더 빨리 읽을 수 있어야합니다. 시도해보고 나에게 궁금 해서요 :)

+0

우스운 이야기지만, 이것은> 1이되면 멈 춥니 다. 흠, 알아 내야 할 이유가 있습니다. – goetzmoritz

+0

BLOCK_SIZE를 500으로 줄이면 다음과 같이 나타납니다. [SQLITE_ERROR] SQL 오류 또는 누락 된 데이터베이스 (복합 SELECT의 용어가 너무 많음). 내가 BLOCK_SIZE에 100을 사용할 때 preparestatement와 같이 빨리 수행하지는 않지만 :-D – goetzmoritz

+0

복합 SELECT의 용어의 한계에 대해 알지 못했습니다. 뭔가를 배웠던 것 같아요. 내 아이디어를 생각합니다. 단일 색인 열에서 더 빨리 읽는 것이 i와 j 둘 모두에서 선택하는 것보다 효과적입니다. 내가 제안한 테이블 구조로 preparedStatement를 사용하십시오. – elbuild