Android + sqlite插入速度提升?

问题描述:

我最近继承了一个项目,其中一个sqlite数据库存储在用户sdcard(仅限表格和列,没有内容)。对于初始安装(和随后的数据更新),XML文件经由SAXParser的解析存储它的内容的分贝列像这样:Android + sqlite插入速度提升?

的SAXParser:

@Override 
    public void endElement(String uri, String localName, String qName) throws SAXException { 
      currentElement = false; 

      if (localName.equals("StoreID")) { 
       buffer.toString().trim(); 
       storeDetails.setStoreId(buffer.toString()); 
      } else if (localName.equals("StoreName")) { 
       buffer.toString().trim(); 
       storeDetails.setStoreName(buffer.toString()); 
      ... 

      } else if (localName.equals("StoreDescription")) { 
       buffer.toString().trim(); 
       storeDetails.setStoreDescription(buffer.toString()); 
       // when the final column is checked, call custom db helper method 
       dBHelper.addtoStoreDetail(storeDetails); 
      } 

      buffer = new StringBuffer(); 
    }   


    @Override 
    public void characters(char[] ch, int start, int length) throws SAXException { 
     if (currentElement) { 
      buffer.append(ch, start, length); 
     } 
    } 

DatabaseHelper:

// add to StoreDetails table 
    public void addtoStoreDetail(StoreDetails storeDetails) { 
     SQLiteDatabase database = null; 
     InsertHelper ih = null; 
     try { 
      database = getWritableDatabase(); 
      ih = new InsertHelper(database, "StoreDetails"); 

      // Get the numeric indexes for each of the columns that we're updating 
      final int idColumn = ih.getColumnIndex("_id"); 
      final int nameColumn = ih.getColumnIndex("StoreName"); 
      ... 
      final int descColumn = ih.getColumnIndex("StoreDescription"); 

      // Add the data for each column 
      ih.bind(idColumn, storeDetails.getStoreId()); 
      ih.bind(nameColumn, storeDetails.getStoreName()); 
      ... 
      ih.bind(descColumn, storeDetails.getStoreDescription()); 

      // Insert the row into the database. 
      ih.execute(); 
     } finally { 
      ih.close(); 
      safeCloseDataBase(database); 
     } 
    } 

加载的xml文档长度超过6000行。当在设备上进行测试时,它会在中途停止插入(无错误),大约需要4-5分钟。然而,在模拟器上,它运行速度相当快,大约20秒内将所有行写入数据库。我有打开db,添加数据,然后关闭时运行的日志语句。在设备上运行时,LogCat输出显着较慢。有什么我在这里失踪?为什么我的数据需要很长时间才能写出来?我认为改进后的InsertHelper会有所帮助,但不幸的是速度并不快。有人可以在这里指出我的缺点吗?

我也指望InsertHelper明显提高了速度,但是当我测试它时差别不是那么大。

InsertHelper的强度仍然是多次插入,因为它只编译一次查询。你这样做的方式是为每个插入声明新的InsertHelper,这是绕过一次性编译改进。尝试使用同一个实例进行多次插入。

但是,我不认为在慢速设备上6000+插入会在一分钟内完成。

编辑还要确保你只取一次列索引,这会加快一点。将这些放置在批次插入的循环外部。

// Get the numeric indexes for each of the columns that we're updating 
final int idColumn = ih.getColumnIndex("_id"); 
final int nameColumn = ih.getColumnIndex("StoreName"); 
final int descColumn = ih.getColumnIndex("StoreDescription"); 
+0

感谢您的回复。好吧,我改变了这个:dBHelper.addtoStoreDetail(storeDetails);到这个:arrayList.add(StoreDetails);当我遍历列表来启动InsertHelper舞蹈时,我的arrayList只包含最后一行......为什么“添加”只添加最后一行?一旦这样排序,我应该回到正轨。 – worked 2012-04-07 23:17:07

+0

@worked:代码在哪里?没有代码,我无法帮助。 – 2012-04-08 07:58:32

当你像这样进行批量插入时,你可能会更好地在DB助手中为它设置一个特殊的操作。现在,每次插入一行时,都会打开和关闭与SQLite数据库的连接,这会显着降低您的速度。对于批处理过程,请将其设置为可以维护整个导入作业的连接。我认为在仿真器中速度更快的原因是,在运行时,仿真器完全存在于内存中 - 因此,尽管它有意降低CPU速度,但File IO速度要快得多。

除了连接数据库只有一次可以在数据库连接设置不要在批次结束提交每个插入后的变化,但只有一次?我试图浏览Android开发文档,但找不到确切的说明如何做到这一点(或者它已经这样设置)。在其他平台上将SQLite驱动程序的AutoCommit设置为false,并且仅在批处理结束时进行提交才能显着提高插入速度。