0

私は最近、ユーザーのSDカードにsqlite dbが保存されているプロジェクトを継承しました(テーブルと列のみ、コンテンツなし)。初期インストール (およびその後のデータ更新) では、saxParser を介して XML ファイルが解析され、次のように内容が db 列に格納されます。

saxパーサー:

    @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、すべての挿入に対して new を宣言します。これは、1 回限りのコンパイルの改善をバイパスしています。複数の挿入に同じインスタンスを使用してみてください。

ただし、遅いデバイスでは 6000 回以上の挿入が 1 分以内に完了するとは思いません。

編集また、列インデックスを一度だけフェッチするようにしてください。これにより、もう少し高速になります。これらをバッチ挿入のループの外側に配置します。

 // 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

データベースを一度だけ接続することに加えて、各挿入後に変更をコミットするのではなく、バッチの最後に一度だけデータベース接続を設定できますか? Android dev docs を参照しようとしましたが、これを行うための正確な手順が見つかりませんでした (または、既に設定されています)。他のプラットフォームでは、SQLite ドライバーの AutoCommit を false に設定し、バッチの最後にのみコミットすると、挿入速度が大幅に向上します。

于 2012-04-07T20:20:09.163 に答える
0

このようなバッチ挿入を行う場合、DB ヘルパーで特別なアクションを設定したほうがよい場合があります。現在、行を挿入するたびに SQLite DB への接続を開いたり閉じたりしているため、大幅に速度が低下します。バッチ処理の場合は、インポートジョブ全体で接続を維持できるように設定してください。エミュレーターの方が速い理由は、実行中にエミュレーターが完全にメモリ内に存在するためだと思います。そのため、意図的に CPU 速度を遅くしますが、ファイル IO ははるかに高速になります。

于 2012-04-07T18:50:54.893 に答える