我最近继承了一个项目,其中sqlite数据库存储在用户sdcard上(仅限表和列,没有内容)。对于初始安装(以及后续数据更新),通过saxParser解析XML文件,将其内容存储到db列,如下所示:
的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秒内将所有行写入数据库。我有日志语句,当数据库打开,数据添加,然后关闭时运行。在设备上运行时,LogCat输出明显变慢。这里有什么我想念的吗?为什么我的数据写这么长时间?我认为改进的InsertHelper会有所帮助,但遗憾的是甚至没有更快。有人能指出我的缺陷吗?
答案 0 :(得分:1)
我还指望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");
答案 1 :(得分:0)
当您进行这样的批量插入时,您最好在数据库助手中为它设置一个特殊操作。现在,每次插入行时都会打开和关闭与SQLite DB的连接,这会显着降低您的速度。对于批处理,请对其进行设置,以便维护整个导入作业的连接。我认为它在模拟器中速度更快的原因是,在运行时,模拟器完全存在于内存中 - 因此尽管故意降低CPU速度,但文件IO的速度要快得多。
答案 2 :(得分:0)
除了只连接数据库一次,数据库连接是否可以设置为不在每次插入后提交更改,而只在批处理结束时提交一次?我试图浏览Android开发文档,但无法找到如何执行此操作的确切说明(或者已经设置好了)。在其他平台上,将SQLite驱动程序的AutoCommit设置为false并仅在批处理结束时提交可以显着提高插入速度。