【问题标题】:Java sqlite performing thousands of queriesJava sqlite 执行数千个查询
【发布时间】:2016-12-02 01:59:41
【问题描述】:

我有一个 java 程序,我在一个循环内对 SQLite 数据库执行数千个查询。如果查询显示为空,则插入该行。如果查询有结果,我忽略。我通常以 1000 个批次执行这些单个查询,但最终将有数十万个查询来完成这项任务。

因为我有数千行要检查单个查询,所以这部分程序运行非常缓慢。

有没有更有效的方法来执行这么多查询?

这是不断从 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;

}

谢谢!

【问题讨论】:

  • 那么问题是什么?
  • 重用stmt。你有索引吗?
  • @VHS 对于超过 100,000 个单独的查询,查询速度太慢。我怎样才能加快速度?
  • @CL。我没有设置任何索引。

标签: java sqlite


【解决方案1】:

在没有任何索引的情况下,查找所需的行需要数据库在每次查询执行时遍历整个表。

您可以通过索引两个查找列来优化此特定查询中的查找:

CREATE INDEX whatever ON AllRecords(ArchiveID, DivaCat);

【讨论】:

  • 谢谢!速度大幅提升。
【解决方案2】:

您的 isInDB 方法每次都连接到数据库。你不需要它。你也可以只用一个查询来做到这一点。

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 结果检查您的每一行。

【讨论】:

  • 可能应该为此使用 StringBuilder
猜你喜欢
  • 2012-07-14
  • 1970-01-01
  • 2018-10-29
  • 2021-09-23
  • 1970-01-01
  • 2014-07-21
  • 2014-12-27
  • 2011-08-28
  • 1970-01-01
相关资源
最近更新 更多