1.利用android提高的的insert,query,update,deleteAPI与execSql,rawQuery函数执行原生的插入,查询,更新,删除语句操作花费时间的对比结果
2014-07-02 18:04
447 查看
[b] 1.利用android提高的的insert,query,update,deleteAPI与execSql,rawQuery函数执行原生的插入,查询,更新,删除语句操作花费时间的对比结果[/b]
在相同的环境(adnroid4.0)和相同的机器下执行相同的动作,记录条数也一样的情况下的对比,多次验证的如下:
(1)如果批量执行的记录数在1000条,则Android SqliteDatabase提供的insert,query,update,delete函数和直接写SQL文的execSql,rawQuery的效率差不多,几乎一样。所以使用哪种放到都可以,不会影响到执行效率。
(2)如果批量执行的记录数在10万条,则会存在差别。在某台手机上SqliteDatabase提供的insert执行插入操作耗时45秒,要比execSql插入35秒慢10秒左右。
可见在数据库大的情况下,还是有差别的。execSql省去了拼接sql语句的步骤,要比SqliteDatabase提供的insert,query,update,delete等函数效率高。当数据库越大,差别也越大。
[b]2.Sqlite数据库批量操作效率的问题[/b]
应用程序初始化时需要批量的向sqlite中插入大量数据,单独的使用for+Insert方法导致应用响应缓慢, 因为 SQLite的数据库本质上来讲就是一个磁盘上的文件,所以一切的数据库操作其实都会转化为对文件的操作,而频繁的文件操作将会是一个很耗时的过程,会极大地影响数据库存取的速度。sqlite插入数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。初始5000条记录也就是要5000次读写磁盘操作, 将会重复的打开关闭数据库文件5000次,所以速度当然会很慢。而且不能保证所有数据都能同时插入。
解决方法:
添加事务处理,把5000条插入作为一个事务
我们使用SQLite的事务进行控制:
db.beginTransaction(); //手动设置开始事务
try{
//批量处理操作
for(Collection c:colls){
insert(db, c);
}
db.setTransactionSuccessful(); //设置事务处理成功,不设置会自动回滚不提交。
//在setTransactionSuccessful和endTransaction之间不进行任何数据库操作
}catch(Exception e){
MyLog.printStackTraceString(e);
}finally{
db.endTransaction(); //处理完成
}
这样SQLite将把全部要执行的SQL语句先缓存在内存当中,然后等到COMMIT的时候一次性的写入数据库,这样数据库文件只被打开关闭了一次,效率自然大大的提高
对比在android中批量插入数据的3中方式对比(各插入1W条数据所花费的时间):
1、 一个一个插入
Java代码
/**
* 向表中插入数据
*
* @param openHelper
* @param appInfo
* @return
*/
public static boolean insert(SQLiteOpenHelper openHelper,
RemoteAppInfo appInfo) {
if (null == appInfo) {
return true;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
ContentValues values = appInfo.getContentValues();
return -1 != db.insert(RemoteDBHelper.TABLE_APP_REMOTE, null,
values);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != db) {
db.close();
}
}
return false;
}
for (RemoteAppInfo remoteAppInfo : list) {
RemoteDBUtil.insert(helper, remoteAppInfo);
}
耗时:106524ms,也就是106s
2、 开启事务批量插入,使用
SqliteDateBase中的
insert(String table, String nullColumnHack, ContentValues values)
方法
Java代码
/**
* 向表中插入一串数据
*
* @param openHelper
* @param appInfo
* @return 如果成功则返回true,否则返回flase
*/
public static boolean insert(SQLiteOpenHelper openHelper,
List<RemoteAppInfo> list) {
boolean result = true;
if (null == list || list.size() <= 0) {
return true;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
db.beginTransaction();
for (RemoteAppInfo remoteAppInfo : list) {
ContentValues values = remoteAppInfo.getContentValues();
if (db.insert(RemoteDBHelper.TABLE_APP_REMOTE, null, values) < 0) {
result = false;
break;
}
}
if (result) {
db.setTransactionSuccessful();
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != db) {
db.endTransaction();
db.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
耗时:2968ms
3、 开启事务批量插入,使用
SQLiteStatement
Java代码
/**
* 第二种方式批量插入(插入1W条数据耗时:1365ms)
* @param openHelper
* @param list
* @return
*/
public static boolean insertBySql(SQLiteOpenHelper openHelper,
List<RemoteAppInfo> list) {
if (null == openHelper || null == list || list.size() <= 0) {
return false;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
String sql = "insert into " + RemoteDBHelper.TABLE_APP_REMOTE + "("
+ RemoteDBHelper.COL_PKG_NAME + ","// 包名
+ RemoteDBHelper.COL_USER_ACCOUNT + ","// 账号
+ RemoteDBHelper.COL_APP_SOURCE + ","// 来源
+ RemoteDBHelper.COL_SOURCE_UNIQUE + ","// PC mac 地址
+ RemoteDBHelper.COL_MOBILE_UNIQUE + ","// 手机唯一标识
+ RemoteDBHelper.COL_IMEI + ","// 手机IMEI
+ RemoteDBHelper.COL_INSTALL_STATUS + ","// 安装状态
+ RemoteDBHelper.COL_TRANSFER_RESULT + ","// 传输状态
+ RemoteDBHelper.COL_REMOTE_RECORD_ID // 唯一标识
+ ") " + "values(?,?,?,?,?,?,?,?,?)";
SQLiteStatement stat = db.compileStatement(sql);
db.beginTransaction();
for (RemoteAppInfo remoteAppInfo : list) {
stat.bindString(1, remoteAppInfo.getPkgName());
stat.bindString(2, remoteAppInfo.getAccount());
stat.bindLong(3, remoteAppInfo.getFrom());
stat.bindString(4, remoteAppInfo.getFromDeviceMd5());
stat.bindString(5, remoteAppInfo.getMoblieMd5());
stat.bindString(6, remoteAppInfo.getImei());
stat.bindLong(7, remoteAppInfo.getInstallStatus());
stat.bindLong(8, remoteAppInfo.getTransferResult());
stat.bindString(9, remoteAppInfo.getRecordId());
long result = stat.executeInsert();
if (result < 0) {
return false;
}
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != db) {
db.endTransaction();
db.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
耗时:1365ms
在相同的环境(adnroid4.0)和相同的机器下执行相同的动作,记录条数也一样的情况下的对比,多次验证的如下:
(1)如果批量执行的记录数在1000条,则Android SqliteDatabase提供的insert,query,update,delete函数和直接写SQL文的execSql,rawQuery的效率差不多,几乎一样。所以使用哪种放到都可以,不会影响到执行效率。
(2)如果批量执行的记录数在10万条,则会存在差别。在某台手机上SqliteDatabase提供的insert执行插入操作耗时45秒,要比execSql插入35秒慢10秒左右。
可见在数据库大的情况下,还是有差别的。execSql省去了拼接sql语句的步骤,要比SqliteDatabase提供的insert,query,update,delete等函数效率高。当数据库越大,差别也越大。
[b]2.Sqlite数据库批量操作效率的问题[/b]
应用程序初始化时需要批量的向sqlite中插入大量数据,单独的使用for+Insert方法导致应用响应缓慢, 因为 SQLite的数据库本质上来讲就是一个磁盘上的文件,所以一切的数据库操作其实都会转化为对文件的操作,而频繁的文件操作将会是一个很耗时的过程,会极大地影响数据库存取的速度。sqlite插入数据的时候默认一条语句就是一个事务,有多少条数据就有多少次磁盘操作。初始5000条记录也就是要5000次读写磁盘操作, 将会重复的打开关闭数据库文件5000次,所以速度当然会很慢。而且不能保证所有数据都能同时插入。
解决方法:
添加事务处理,把5000条插入作为一个事务
我们使用SQLite的事务进行控制:
db.beginTransaction(); //手动设置开始事务
try{
//批量处理操作
for(Collection c:colls){
insert(db, c);
}
db.setTransactionSuccessful(); //设置事务处理成功,不设置会自动回滚不提交。
//在setTransactionSuccessful和endTransaction之间不进行任何数据库操作
}catch(Exception e){
MyLog.printStackTraceString(e);
}finally{
db.endTransaction(); //处理完成
}
这样SQLite将把全部要执行的SQL语句先缓存在内存当中,然后等到COMMIT的时候一次性的写入数据库,这样数据库文件只被打开关闭了一次,效率自然大大的提高
对比在android中批量插入数据的3中方式对比(各插入1W条数据所花费的时间):
1、 一个一个插入
Java代码
/**
* 向表中插入数据
*
* @param openHelper
* @param appInfo
* @return
*/
public static boolean insert(SQLiteOpenHelper openHelper,
RemoteAppInfo appInfo) {
if (null == appInfo) {
return true;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
ContentValues values = appInfo.getContentValues();
return -1 != db.insert(RemoteDBHelper.TABLE_APP_REMOTE, null,
values);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != db) {
db.close();
}
}
return false;
}
for (RemoteAppInfo remoteAppInfo : list) {
RemoteDBUtil.insert(helper, remoteAppInfo);
}
耗时:106524ms,也就是106s
2、 开启事务批量插入,使用
SqliteDateBase中的
insert(String table, String nullColumnHack, ContentValues values)
方法
Java代码
/**
* 向表中插入一串数据
*
* @param openHelper
* @param appInfo
* @return 如果成功则返回true,否则返回flase
*/
public static boolean insert(SQLiteOpenHelper openHelper,
List<RemoteAppInfo> list) {
boolean result = true;
if (null == list || list.size() <= 0) {
return true;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
db.beginTransaction();
for (RemoteAppInfo remoteAppInfo : list) {
ContentValues values = remoteAppInfo.getContentValues();
if (db.insert(RemoteDBHelper.TABLE_APP_REMOTE, null, values) < 0) {
result = false;
break;
}
}
if (result) {
db.setTransactionSuccessful();
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != db) {
db.endTransaction();
db.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
耗时:2968ms
3、 开启事务批量插入,使用
SQLiteStatement
Java代码
/**
* 第二种方式批量插入(插入1W条数据耗时:1365ms)
* @param openHelper
* @param list
* @return
*/
public static boolean insertBySql(SQLiteOpenHelper openHelper,
List<RemoteAppInfo> list) {
if (null == openHelper || null == list || list.size() <= 0) {
return false;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
String sql = "insert into " + RemoteDBHelper.TABLE_APP_REMOTE + "("
+ RemoteDBHelper.COL_PKG_NAME + ","// 包名
+ RemoteDBHelper.COL_USER_ACCOUNT + ","// 账号
+ RemoteDBHelper.COL_APP_SOURCE + ","// 来源
+ RemoteDBHelper.COL_SOURCE_UNIQUE + ","// PC mac 地址
+ RemoteDBHelper.COL_MOBILE_UNIQUE + ","// 手机唯一标识
+ RemoteDBHelper.COL_IMEI + ","// 手机IMEI
+ RemoteDBHelper.COL_INSTALL_STATUS + ","// 安装状态
+ RemoteDBHelper.COL_TRANSFER_RESULT + ","// 传输状态
+ RemoteDBHelper.COL_REMOTE_RECORD_ID // 唯一标识
+ ") " + "values(?,?,?,?,?,?,?,?,?)";
SQLiteStatement stat = db.compileStatement(sql);
db.beginTransaction();
for (RemoteAppInfo remoteAppInfo : list) {
stat.bindString(1, remoteAppInfo.getPkgName());
stat.bindString(2, remoteAppInfo.getAccount());
stat.bindLong(3, remoteAppInfo.getFrom());
stat.bindString(4, remoteAppInfo.getFromDeviceMd5());
stat.bindString(5, remoteAppInfo.getMoblieMd5());
stat.bindString(6, remoteAppInfo.getImei());
stat.bindLong(7, remoteAppInfo.getInstallStatus());
stat.bindLong(8, remoteAppInfo.getTransferResult());
stat.bindString(9, remoteAppInfo.getRecordId());
long result = stat.executeInsert();
if (result < 0) {
return false;
}
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != db) {
db.endTransaction();
db.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
耗时:1365ms
相关文章推荐
- 利用android提高的的insert,query,update,deleteAPI与execSql,rawQuery函数执行原生的插入,查询,更新,删除语
- 利用android提高的的insert,query,update,deleteAPI与execSql,rawQuery函数执行原生的插入,查询,更新,删除语
- Chapter 3. SQL Server数据库、表的基本操作(insert插入、update更新、delete、truncate删除语句)
- Android Sqlite数据库执行插入查询更新删除的操作对比
- Android Sqlite数据库执行插入查询更新删除的操作对比
- Android Sqlite数据库执行插入查询更新删除的操作对比
- MySQL--操作简记(create创建操纵表、insert插入、update更新、delete删除数据)
- Android 之采用execSQL和rawQuery方法完成数据的添删改查操作 原生的查询和执行!!
- jsp操作MySQL实现查询、插入与删除功能(query、insert、delete)
- discuz 如何添加数据DB::insert和更新数据DB::update 查询DB::query删除DB::delete
- 表的三种基本操作:插入(insert)、删除(delete)、更新(update)
- MYSQL数据库(十)- 数据表的插入(insert)、删(delete)、改(update)、查(select)、group by 分组、having语句设置分组条件,order by查询结果排序,
- SQL_4th_插入insert、查询select、删除delete、更新update
- discuz 如何添加数据DB::insert和更新数据DB::update 查询DB::query删除DB::delete
- Android Sqlite数据库执行插入查询更新删除的操作对比
- Day53、表连接、合并结果集、组函数和分组、子查询、表操作(创建、删除、更新)、事务控制语句
- MySQL学习系列7:插入insert 更新update 删除delete
- 二叉搜索树的查询、插入与删除操作(Binary Search Tree, Search, Insert, Delete)(C++)
- 连接excel执行Insert Into语句出现“操作必须使用一个可更新的查询”的解决
- 我想操作的是利用SqlDataAdapter的几个Command属性(InsertCommand,UpdateCommand,DeleteCommand)来更新数据库