最初のJavaアプリケーションを書いた人が、Androidのすぐ下でさえ、何をいじらなければならなかったかについて、長い話をしたくありません。 私の意見では、あなたを物語で退屈させるのではなく、すぐにビジネスに取り掛かる方が良いと思います。 結局のところ、ここで見たのは答えだったのですか?
そうだった。 単純に、DBHelperはシングルトンを介して実装され、データベースオブジェクトは同じ方法で保存されました。
public class DBHelper extends SQLiteOpenHelper { ... private static DBHelper instance; private static SQLiteDatabase db; public static DBHelper getInstance() { if (instance == null) instance = new DBHelper(Pleazzme.getAppContext()); return instance; } public static SQLiteDatabase getDB() { if (db == null) db = getInstance().getWritableDatabase(); return db; } ... }
別のAsyncTaskでパーサーが起動され、ループ内でsave()メソッドを使用してオブジェクトが提供されました。
... public void save() { ContentValues values = new ContentValues(); values.put(id, Id); values.put(name, Name); values.put(categoriesIds, App.gson.toJson(CategoriesIds)); values.put(datecreated, DateCreated.getTime()); Document.save(); values.put(document_id, Document.getId()); values.put(hasbarcode, hasBarcode); values.put(headofficeaddress, HeadOfficeAddress); values.put(phonenumbers, PhoneNumbers); values.put(website, WebSite); values.put(popularity, Popularity); values.put(keywords, Keywords); DBHelper.getDB().insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE); } ...
この状況では、オブジェクトをデータベースに40〜50ミリ秒保存しました。 その結果、少なくとも4分間、すべての保存が私に注がれました。 当然、これはユーザーには適していませんでした。 そして、挿入を高速化するソリューションのために検索エンジンとインターネットを喫煙し始めました。 答えはこことドキュメントにありました。
プロセスを高速化するために、次の手順が実行されました。
- ContentValuesの代わりにInsertHelperを使用します
- 大規模な挿入を開始する前に、データベースの同期をオフにし、すべてをロックして1つのトランザクションに入れます
- 上記のすべてを正しく動作させるには、非同期で取り出されたデータベースオブジェクトを各オブジェクトのsave()メソッドに転送する必要があります。そうしないと、例外が発生します
コードがより雄弁であることを考えると、最終的にデザインは次のようになります。
public class DBHelper extends SQLiteOpenHelper { ... private static DBHelper instance; private static SQLiteDatabase db; public static DBHelper getInstance() { if (instance == null) instance = new DBHelper(Pleazzme.getAppContext()); return instance; } public static SQLiteDatabase getDB() { if (db == null) db = getInstance().getWritableDatabase(); return db; } ... /*new code*/ public static void bigDataBegin(SQLiteDatabase _db){ //_db.setLockingEnabled(false); //_db.execSQL("PRAGMA synchronous=0"); _db.beginTransaction(); } public static void bigDataEnd(SQLiteDatabase _db){ //_db.setLockingEnabled(true); //_db.execSQL("PRAGMA synchronous=1"); _db.setTransactionSuccessful(); _db.endTransaction(); } }
保存されたオブジェクトクラス:
... private static InsertHelper ih; public void save(final SQLiteDatabase db) { if(ih == null) ih = new InsertHelper(db, table); ih.prepareForInsert(); try { ih.bind(ih.getColumnIndex(key), value); } catch (NullPointerException e) { } ..... ih.execute(); ih.close(); } ...
そして、これらすべてがオブジェクトを保存するためのコードを「離陸」します。
SQLiteDatabase database = DBHelper.getDB(); DBHelper.bigDataBegin(database); for (int i = 0; i < currSize; i++) { gson.fromJson(o, Data.class).save(database); } DBHelper.bigDataEnd(database);
すべての操作と速度の測定の後、結果は次のようになりました。
- オブジェクトごとに最大-40ms
- 後-オブジェクトごとに4ミリ秒
この情報が誰かに役立つことを願っています。 まず第一に、初心者プログラマー向けに設計されています。 誰かがより効果的なオプションを提供できるなら、私は嬉しいだけです。
UPD。
意識のない喜びの爆発の中で、私は発見を共有しました。 テスト後、別のパラレルスレッドでデータを追加しようとすると、ayahが追加され、さらに一部のデバイスはプラグマを直接使用しようとすることを誓うことが判明しました。
したがって、1つのトランザクションの使用のみが残ります(エラーコードをコメント化しました)。 この形式では、可能な限り安全なままです。 確かに、同時に、ドキュメントよりも多くの情報を運ぶものに対するすべての主張を失います。
私にとって別の興味深い事実は、弟(HTC Wildfire)が顕著な増加を示さなかったにもかかわらず、パワフルなデバイス(たとえば、4.0.4搭載のSGS2)で顕著なパフォーマンスの向上が観察されたことです...