0

我最近继承了一个项目,其中一个 sqlite db 存储在用户 sdcard 上(只有表和列,没有内容)。对于初始安装(和后续数据更新),通过 saxParser 解析 XML 文件,将其内容存储到 db 列,如下所示:

萨克斯解析器:

    @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 分钟。然而,在模拟器上,它运行得相当快,在大约 20 秒内将所有行写入数据库。我有在打开数据库、添加数据然后关闭时运行的日志语句。在设备上运行时,LogCat 输出明显变慢。我在这里缺少什么吗?为什么我的数据需要这么长时间才能写入?我认为改进的 InsertHelper 会有所帮助,但不幸的是甚至没有更快。有人可以在这里指出我的缺陷吗?

4

3 回答 3

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");
于 2012-04-07T18:53:35.867 回答
0

当您进行这样的批量插入时,您最好在数据库助手中为它设置一个特殊操作。现在,每次插入一行时,您都在打开和关闭与 SQLite DB 的连接,这会大大降低您的速度。对于批处理,进行设置,以便您可以维护整个导入作业的连接。我认为它在模拟器中更快的原因是,在运行时,模拟器完全存在于内存中 - 所以虽然它故意降低你的 CPU 速度,但文件 IO 的速度要快得多。

于 2012-04-07T18:50:54.893 回答
0

除了只连接一次数据库之外,是否可以将数据库连接设置为在每次插入后不提交更改,而在批处理结束时只提交一次?我试图浏览 Android 开发文档,但找不到如何执行此操作的确切说明(或者它已经设置好了)。在其他平台上,将 SQLite 驱动程序的 AutoCommit 设置为 false 并仅在批处理结束时提交可以显着提高插入速度。

于 2012-04-07T20:20:09.163 回答