2016-11-30 20 views
1

ループ内のSQLiteデータベースで何千ものクエリを実行するJavaプログラムがあります。クエリが空の場合は、行を挿入します。クエリに結果がある場合、私は無視します。私は一般に、これらの個々のクエリを1000のバッチで実行しますが、最終的にこのタスクを完了するために数十万のクエリが存在します。Java sqliteは何千ものクエリを実行しています

私は個々のクエリでチェックしている数千の行があるので、プログラムのこの部分は非常にゆっくり実行されます。

このようなクエリをより効率的に実行する方法はありますか?ここで

は、すべての情報が読み込まれるまで常にExcelのドキュメントから元のデータを引き出しループである:ここでは

for(int i =0;i < batchSize;i++){ 
    try { 
     String[] rowReader=(dataRows.get(i)); 
     archiveID=rowReader[16]; 
     DIVA = rowReader[41]; 

     //Check if already in DB. If it is not, then adds to a batch 
     System.out.println("checking db"); 
     if(!isInDB(conn, archiveID, DIVA)){ 
      stmt.setString(1,archiveID); 
      stmt.setString(2,DIVA); 
      stmt.setString(3,docName); 
      stmt.addBatch(); 
     } 

    }catch (IndexOutOfBoundsException ex){ 
     endOfDoc = true; 
    } 

    //dump to database every batchSize 
    if(++count % batchSize == 0) { 
     //System.out.println("executing batch"); 
     stmt.executeBatch(); 
     conn.commit(); 
     count=0; 
    } 
} 

は、実際のクエリメソッドです:

//returns false if combo is not in All Records, returns true if there 
public static boolean isInDB(Connection conn, String archiveID, String DIVA) throws SQLException { 
    Connection c = conn; 
    Statement stmt = null; 
    try { 
     Class.forName("org.sqlite.JDBC"); 

     stmt = c.createStatement(); 
     ResultSet rs = stmt.executeQuery("SELECT * FROM AllRecords WHERE ArchiveID=\"" + archiveID +"\" AND DivaCat=\""+DIVA +"\""); 
     if (rs.next()) { 
     return true; 
     }else{ 
      System.out.println(archiveID+DIVA+" is not in DB"); 
      rs.close(); 
      stmt.close(); 
      return false; 

     } 
    } catch (Exception e) { 
     System.err.println(e.getClass().getName() + ": " + e.getMessage()); 
     System.exit(0); 
    } 
    return false; 

} 

ありがとう!

+2

そこで質問は何ですか? – VHS

+0

'stmt'を再利用します。インデックスはありますか? –

+0

@VHSクエリはあまりにも遅すぎて、100,000を超える個々のクエリがありません。どうすればそれをスピードアップできますか? –

答えて

0

インデックスが1つもない場合、クエリの実行ごとにデータベース全体がテーブルを通過する必要があります。

あなたは、両方のルックアップ列に索引を付けることで、この特定のクエリで検索を最適化することができます。

CREATE INDEX whatever ON AllRecords(ArchiveID, DivaCat); 
+1

ありがとう!大幅なスピードアップ。 –

0

isInDBメソッドは、毎回データベースに接続します。あなたはそれを必要としません。 1つのクエリでもそれを行うことができます。

sqlQuery = "SELECT * FROM AllRecords WHERE " 

for(int i =0;i < batchSize;i++){ 
    ... 
    if(i ==0) 
     sqlQuery + = "ArchiveID=\"" + archiveID +"\" AND DivaCat=\""+DIVA +"\""; 
    else 
     sqlQuery + = " OR ArchiveID=\"" + archiveID +"\" AND DivaCat=\""+DIVA +"\""; 

その後、sqlQueryクエリを実行し、rs結果で各行をチェックします。

+2

おそらくこのためにStringBuilderを使うべきです –

関連する問題