java - SQLite:什么插入策略更好?一大批还是许多小批?

标签 java android sqlite

在我的应用程序中,我从服务器获取一些数据,在反序列化(从 JSON 到对象)之后,我将把这些对象放入我的数据库中。直到今天我才采取了方法:

for(int i=0; i<receivedJsonArray.length; i++)
    Bean bean = new Bean();
    //matching some parameters
    //...
    dao.putObject(bean);
 }

我的 dao.putObject(Bean) 的样子(我省略了一些东西,比如 try-catch block ,因为它们并不真正相关)。

 public void putObject(Bean bean){
     sqliteDatabase.beginTransaction();
     ContentValues values = new ContentValues();
     values.put("something", bean.getSomething());
     // ... some mapping
     database.insert("table", null, values);
     database.setTransactionSuccessful();
     database.endTransaction();
 }

正如您在此处看到的那样,每次反序列化对象的单个实例时,我都会进行新的事务等等。但是,我觉得我使用了第二种方法中使用的一小部分内存。

Bean[] beans = new Bean[receivedJsonArray.length]; 
for(int i=0; i<receivedJsonArray.length; i++)
    Bean bean = new Bean();
    //matching some parameters
    //...
    beans[i] = bean;
}
dao.putObject(beans);

现在 dao.putObject(Bean...) 看起来像

 public void putObject(Bean... beans){
     sqliteDatabase.beginTransaction();
     for(int i=0; i<beans.length; i++){
          ContentValues values = new ContentValues();
          values.put("something", beans[i].getSomething());
          // ... some mapping
          database.insert("table", null, values);
     }
     database.setTransactionSuccessful();
     database.endTransaction();
 }

所以现在我想知道这两种方法中哪一种是处理大约 400-500 个对象的更好方法?我觉得开始和结束交易 400-500 次是一个不好的做法。另一方面,我对创建和保存相当大的数据集合感到难过。
我知道在我的应用程序的目标设备(Android 4.+)中,这并不重要,因为我拥有高效的 CPU 和相当多的 RAM;但是我觉得这不是低效代码的借口。

那么,你建议如何?一大批,插入每个对象,或者尝试一次插入一堆(即 100 个对象)?

最佳答案

我测量了时间,结果非常明确。

使用的 DAO 方法如下所示:

public void addObject(Bean ... beans) {
    SQLiteDatabase database = dbHelper.openDatabase();
    database.beginTransaction();
    try{
        for(int i=0; i<roomBeans.length; i++) {
            ContentValues values = new ContentValues();
            //putting stuff in values
            database.insertWithOnConflict("table", null, values, SQLiteDatabase.CONFLICT_REPLACE);
        }
        database.setTransactionSuccessful();
    }catch(SQLException e) {
        Log.e(AppConstants.DEBUG_TAG, e.toString());
    }finally {
        database.endTransaction();
    }
    dbHelper.closeDatabase();
}

我测量的内容:

方法#1:

        DAO.deleteRows(); // so I'm inserting into an empty table
        long time = new Date().getTime();
        for(int i=0; i<objectsArray.length()*50; i++){
            JSONArray entry = (JSONArray) objectsArray.get(i%objectsArray.length());

            Bean bean = new Bean();
            bean.setStuff(entry.getInt(0));
            // and so on...
            dao.addObject(bean);
        }

        long timeFinish = new Date().getTime();
        long timeTotal = timeFinish - time;

方法#2:

        DAO.deleteRows(); // so I'm inserting into an empty table
        long time = new Date().getTime();
        Bean[] beans = new Bean[objectsArray.length()*50];
        for(int i=0; i<objectsArray.length()*50; i++){
            JSONArray entry = (JSONArray) objectsArray.get(i%objectsArray.length());

            Bean bean = new Bean();
            bean.setStuff(entry.getInt(0));
            // and so on...
            beans[i] = bean;
        }
        dao.addObject(beans);
        long timeFinish = new Date().getTime();
        long timeTotal = timeFinish - time;

结果:

每种方法都经过十次测试,以确保结果具有一定的可重复性。

方法 #1timeTotal
20628、20964、19699、19380、20299、 20553、19715、18239、20267、18711
方法 #2timeTotal
1289、1333、1288、1388、1294、 1393、1344、1334、1376、1360

摘要:
这里的数字胜于 Eloquent 。我不知道如何检查这里使用的确切内存量,但即使我使用 1-2 MB 的 RAM(考虑到我使用的 Bean 的结构,这是 IMO 的极端预测)2 秒,也不会发生任何错误假设这个 Bean[] 数组是一个局部变量。离开方法的范围后,它应该很快就会被 GC 处理,每个人都应该感到高兴。这些结果可能还取决于表和数据本身的 SQL 逻辑。

如果您不同意我的观点,请随时发表评论。

关于java - SQLite:什么插入策略更好?一大批还是许多小批?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29662479/

相关文章:

javascript - Android 键盘在验证后无法在 webview 中工作

Android 与跨多个应用的​​现有服务绑定(bind)

android - 数据绑定(bind) : How to get resource by dynamic id?

android - android中反复出现不明确的列名_id sqlite错误

java - 如何sqlite + listview + onListItemClick启动新的Activity?光标读取错误

java - java继承隐藏方法

java - Android 上的 ReSTLet 客户端 : can't get off the ground :(

java - 在 firebase 数据库中搜索 Sport 而不是 Gender

java - wsdl2java地址存在时端口中的端点地址无效

java - 从小部件类连接到数据库