8

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

插入记录时,我看到性能非常差。我知道外部存储器可能很慢,但我想看到一些数字,所以我写了一个小应用程序来测试它。

这是代码:

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,内部存储器

      方法 | 记录 | 时间(毫秒)| 每秒记录数
-------------+---------+------------+-------------- ------
      正常 | 100 | 2072 | 48.26
插入助手 | 100 | 1662 | 60.17


Nexus One,外部存储器:

      方法 | 记录 | 时间(毫秒)| 每秒记录数
-------------+---------+------------+-------------- ------
      正常 | 100 | 7390 | 13.53
插入助手 | 100 | 7152 | 13.98


模拟器,内部存储器:

      方法 | 记录 | 时间(毫秒)| 每秒记录数
-------------+---------+------------+-------------- ------
      正常 | 100 | 1803 | 55.46
插入助手 | 100 | 3075 | 32.52


仿真器,外部存储器:

      方法 | 记录 | 时间(毫秒)| 每秒记录数
-------------+---------+------------+-------------- ------
      正常 | 100 | 5742 | 17.42
插入助手 | 100 | 7164 | 13.96

如您所见,模拟器不能被信任,InsertHelper如果有的话应该更快。
当然,这是意料之中的,测试主要是出于好奇。

然而,我担心的是我的手机在使用外部存储器时性能不佳,我是否错过了一些关键方面,SQLiteDatabase或者仅仅是因为 SD 卡会变慢?

我可以在我的真实应用程序中添加它,我禁用了锁定,它几乎没有什么区别。

4

2 回答 2

14

CommonsWare 在他的评论中是正确的。对数据库性能有很大影响的是使用事务。将您的插入循环包装在事务中。我不是 100% 确定它是否可以与 InsertHelper 一起使用,但你可以尝试用这个替换你的 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();
}
于 2011-06-15T01:10:30.830 回答
2

我有一些数据库性能问题,所以我使用你的代码来测量我系统上每秒的插入次数。但我还在 {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
于 2012-03-21T20:36:14.563 回答