Android 安卓&x2B;sqlite插入速度改进?
我最近继承了一个项目,其中sqlite db存储在用户SD卡上(仅表和列,没有内容)。对于初始安装(以及后续数据更新),XML文件通过saxParser进行解析,将其内容存储到db列中,如下所示: saxParser:Android 安卓&x2B;sqlite插入速度改进?,android,database,sqlite,saxparser,sqliteopenhelper,Android,Database,Sqlite,Saxparser,Sqliteopenhelper,我最近继承了一个项目,其中sqlite db存储在用户SD卡上(仅表和列,没有内容)。对于初始安装(以及后续数据更新),XML文件通过saxParser进行解析,将其内容存储到db列中,如下所示: saxParser: @Override public void endElement(String uri, String localName, String qName) throws SAXException { currentElement = fals
@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);
}
}
// 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);
}
}
数据库助手:
@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);
}
}
// 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分钟。然而,在emulator上,它运行得相当快,在大约20秒内将所有行写入数据库。我有在数据库打开、添加数据然后关闭时运行的日志语句。在设备上运行时,LogCat输出速度明显较慢。这里有我遗漏的东西吗?为什么我的数据要花这么长时间来写?我原以为改进后的InsertHelper会有所帮助,但不幸的是,甚至没有更快一点。有人能指出我的缺陷吗?当您执行这样的批量插入时,最好在DB helper中为此设置一个特殊操作。现在,每次插入一行时都要打开和关闭与SQLite DB的连接,这将大大降低速度。对于批处理过程,请将其设置为可以维护整个导入作业的连接。我认为在模拟器中速度更快的原因是,在运行时,模拟器完全存在于内存中-因此,尽管它有意降低CPU速度,但文件IO速度要快得多。我还指望
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");
除了只连接一次数据库之外,是否可以将数据库连接设置为在每次插入后不提交更改,而只在批处理结束时提交一次?我试图浏览Android开发文档,但找不到具体的操作说明(或者已经设置好了)。在其他平台上,将SQLite驱动程序的自动提交设置为false并仅在批处理结束时提交可以显著提高插入速度。感谢您的响应。好的,所以我更改了这个:dBHelper.addtoStoreDetail(storeDetails);添加到:arrayList.add(StoreDetails);当我在列表上循环启动InsertHelper舞蹈时,我的arrayList只包含最后一行。。。为什么“添加”只添加最后一行?一旦这件事解决了,我就应该回到正轨了。