Android + sqlite插入速度提升?

时间:2012-04-07 18:45:46

标签: android database sqlite saxparser sqliteopenhelper

我最近继承了一个项目,其中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会有所帮助,但遗憾的是甚至没有更快。有人能指出我的缺陷吗?

3 个答案:

答案 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并仅在批处理结束时提交可以显着提高插入速度。