Android中外部存储上的SQLite性能不佳

我正在使用外部存储将事件存储在数据库中,等待发送到服务器。

插入logging时,我看到了非常糟糕的performance。 我知道外部存储器可能很慢,但我想看到一些数字,所以我写了一个小应用程序来testing它。

这里是代码:

public static final int INSERTS = 100; File dbFile = new File(Environment.getExternalStorageDirectory(), "test.sqlite3"); // File dbFile = new File(getFilesDir(), "test.sqlite3"); dbFile.delete(); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); db.execSQL("CREATE TABLE events (_id integer primary key autoincrement, event_type TEXT NOT NULL, timestamp BIGINT, data TEXT);"); db.execSQL("CREATE INDEX mainIndex ON events (event_type, timestamp ASC);"); InsertHelper helper = new InsertHelper(db, "events"); final int eventTypeCol = helper.getColumnIndex("event_type"); final int timestampCol = helper.getColumnIndex("timestamp"); final int dataCol = helper.getColumnIndex("data"); long start = System.currentTimeMillis(); String eventType = "foo", data = "bar"; long timestamp = 4711; for(int i = 0; i < INSERTS; ++i) { helper.prepareForInsert(); helper.bind(eventTypeCol, eventType); helper.bind(timestampCol, timestamp); helper.bind(dataCol, data); helper.execute(); } long end = System.currentTimeMillis(); Log.i("Test", String.format("InsertHelper, Speed: %d ms, Records per second: %.2f", (int)(end-start), 1000*(double)INSERTS/(double)(end-start))); db.close(); dbFile.delete(); db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); db.execSQL("CREATE TABLE events (_id integer primary key autoincrement, event_type TEXT NOT NULL, timestamp BIGINT, data TEXT);"); db.execSQL("CREATE INDEX mainIndex ON events (event_type, timestamp ASC);"); start = System.currentTimeMillis(); ContentValues cv = new ContentValues(); for(int i = 0; i < INSERTS; ++i) { cv.put("event_type", eventType); cv.put("timestamp", timestamp); cv.put("data", data); db.insert("events", null, cv); } end = System.currentTimeMillis(); Log.i("Test", String.format("Normal, Speed: %d ms, Records per second: %.2f", end-start, 1000*(double)INSERTS/(double)(end-start))); db.close(); dbFile.delete(); 

数据库是完全一样的,我真正的应用程序正在使用,我试图删除索引,但没有任何区别。

结果如下:

 Nexus One,内存

      方法| logging| 时间(毫秒)| 每秒logging
 ------------- + --------- + ----------- -------------- + ------
      正常|  100 |  2072 |  48.26
 InsertHelper |  100 |  1662 |  60.17


 Nexus One,外部存储器:

      方法| logging| 时间(毫秒)| 每秒logging
 ------------- + --------- + ----------- -------------- + ------
      正常|  100 |  7390 |  13.53
 InsertHelper |  100 |  7152 |  13.98


仿真器,内部存储器:

      方法| logging| 时间(毫秒)| 每秒logging
 ------------- + --------- + ----------- -------------- + ------
      正常|  100 |  1803 |  55.46
 InsertHelper |  100 |  3075 |  32.52


仿真器,外部存储器:

      方法| logging| 时间(毫秒)| 每秒logging
 ------------- + --------- + ----------- -------------- + ------
      正常|  100 |  5742 |  17.42
 InsertHelper |  100 |  7164 |  13.96 

正如你所看到的模拟器不能被信任, InsertHelper应该更快,如果有的话。
这当然是可以预料的,testing主要是出于好奇。

但是我有什么担心的是使用外部存储器时手机的性能不好,我错过了SQLiteDatabase一些关键方面,或者只是为了让SD卡变慢?

我可以在我的真实应用程序添加,我已经禁用locking ,它没有什么区别。

CommonsWare在他的评论中是正确的。 对数据库性能有很大影响的是使用事务。 把你的插入循环包装在一个事务中。 我不是100%确定它是否可以与InsertHelper一起使用,但是你可以尝试用下面的代码replace你的for循环:

 db.beginTransaction(); try { for(int i = 0; i < INSERTS; ++i) { helper.prepareForInsert(); helper.bind(eventTypeCol, eventType); helper.bind(timestampCol, timestamp); helper.bind(dataCol, data); helper.execute(); } db.setTransactionSuccessful(); } finally { db.endTransaction(); } 

我有一些数据库性能问题,所以我用你的代码来测量我的系统每秒插入。 但是我也在{begin,end} Transaction()中添加了换行。

在模拟器中。 我有:

 InsertHelper-Internal-Trans, Speed: 67 ms, Records per second: 1492.54 InsertHelper-External-Trans, Speed: 70 ms, Records per second: 1428.57 Normal-Internal-Trans, Speed: 148 ms, Records per second: 675.68 Normal-External-Trans, Speed: 152 ms, Records per second: 657.89 InsertHelper-Internal-NoTrans, Speed: 514 ms, Records per second: 194.55 Normal-Internal-NoTrans, Speed: 519 ms, Records per second: 192.68 InsertHelper-External-NoTrans, Speed: 590 ms, Records per second: 169.49 Normal-External-NoTrans, Speed: 618 ms, Records per second: 161.81 

而在三星Galaxy Note上:

 InsertHelper-External-Trans, Speed: 52 ms, Records per second: 1923.08 InsertHelper-Internal-Trans, Speed: 52 ms, Records per second: 1923.08 Normal-External-Trans, Speed: 77 ms, Records per second: 1298.70 Normal-Internal-Trans, Speed: 121 ms, Records per second: 826.45 Normal-External-NoTrans, Speed: 4562 ms, Records per second: 21.92 Normal-Internal-NoTrans, Speed: 4855 ms, Records per second: 20.60 InsertHelper-External-NoTrans, Speed: 5997 ms, Records per second: 16.68 InsertHelper-Internal-NoTrans, Speed: 8361 ms, Records per second: 11.96