Android 安卓&x2B;sqlite插入速度改进?

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

我最近继承了一个项目,其中sqlite db存储在用户SD卡上(仅表和列,没有内容)。对于初始安装(以及后续数据更新),XML文件通过saxParser进行解析,将其内容存储到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);
        }
    }
    // 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只包含最后一行。。。为什么“添加”只添加最后一行?一旦这件事解决了,我就应该回到正轨了。