前言
我有一个朋友在开发当中接到一个需求,需要对20w+数据进行下载,并将数据进行增,改,查的处理。
下载数据源是一个整合的压缩包,20w+的数据也就几M大小,所以下载不成问题,主要是操作数据库遇到了一些问题。
使用普通的SQL语句操作或者使用GreenDao自带的Api进行操作
// Api插入、增加20w+/1条数据操作
Query<Person> query = sDaoSession.getPersonDao()
.queryBuilder()
.where(PersonDao.Properties.Idcard.eq(person.getIdcard())).build();
person.setStatus(1);
person.setSync(1);
Person resultPerson = query.unique();
if (resultPerson != null) {
person.setId(resultPerson.getId());
sDaoSession.getPersonDao().update(person);
return;
}
sDaoSession.getPersonDao().insert(person);
或者使用Api进行Sql语句进行20w/1条数据操作插入 ,发现数据增加和更新非常缓慢,20w+数据需要1个小时以上才可以完成数据库的增加和更新。
分析原因(查找导致数据插入缓慢的问题所在)
1.通过logcat 控制台输出的日记发现,greendao在进行数据库操作的时候
,以及查看实现源码可得知每一次进行数据库插入都会进行一次
db.beginTransaction()以及db.endTransaction()操作,这里判断也许是造成缓慢的原因之一。
2.通过问题1 所在继续深入源码可得知每一次操作数据库,greendao 都会进行一次
SQLiteStatement rawStmt = (SQLiteStatement) stmt.getRawStatement()。根据我的经验判断,这两个
地方的对象其实是可以重新复用起来的。
解决
1.先上代码:
public static void insertPersonLock(List<Person> persons) {
sDaoSession.runInTx(new Runnable() {
@Override
public void run() {
DaoConfig dc = new DaoConfig(sDaoSession.getDatabase(), PersonDao.class);
DatabaseStatement insertStatement = dc.statements.getInsertStatement();
String updSql = SqlUtils.createSqlUpdate(dc.tablename, dc.nonPkColumns, new String[]{PersonDao.Properties.Idcard.columnName});
DatabaseStatement updateStmt = sDaoSession.getDatabase().compileStatement(updSql);
for (Person person : persons) {
sDaoSession.getPersonDao().bindValues(insertStatement, person);
try {
insertStatement.executeInsert();
} catch (SQLiteConstraintException e) {
bindValuesUpdPerson(updateStmt, person);
updateStmt.bindString(dc.nonPkColumns.length + 1, person.getIdcard());
updateStmt.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
2.根据上述分析以及查看Api得知GreenDao提供了runInTx(Runnable runable)
用来给用户免去重复进行db.beginTransaction()以及db.endTransaction()操作
但是对单条数据依旧还是原来的套路,但是如果我把相对20w+条的N条进行存储
,那么这N条数据进行数据数据库操作的过程中就不用频繁进行
db.beginTransaction()以及db.endTransaction()操作。
那么 DatabaseStatement insertStatement的创建
以及DatabaseStatement updateStmt的创建也是一样的道理。
结果
20w+数据由原来的1小时+变成了10分钟以内。效果显著。