SQLite 大数据量 新增修改 提升效率的办法

SQLite 大数据量 新增修改 提升效率的办法,第1张

概述一、新增     SQLite中的新增默认是单个事务控制的,一次新增就是一次数据库 *** 作,一次事务。如果几千次for循环 *** 作,必然存在效率问题。下面代码是通过事务控制的方式提升效率: public void addList(List<GroupMember> listMember) { StringBuffer sbSQL = new StringBuffer(); SQLiteDataba 一、新增

sqlite中的新增默认是单个事务控制的,一次新增就是一次数据库 *** 作,一次事务。如果几千次for循环 *** 作,必然存在效率问题。下面代码是通过事务控制的方式提升效率:

public voID addList(List<GroupMember> ListMember) {	StringBuffer sbsql = new StringBuffer();		sqliteDatabase db = super.getDatabase();	db.beginTransaction();	for (int i = 0; i < ListMember.size(); i++) {		GroupMember groupMember = ListMember.get(i);		if(i == 0) {			// 根据当前用户ID和圈子ID删除圈子成员			del(groupMember.getUserID(),groupMember.getGroupID());// 第一次新增的时候删除历史数据		}				if(i != 0) {			sbsql.delete(0,sbsql.length());		}		sbsql.append(" INSERT INTO ").append(table).append(" (user_ID,group_ID,member_ID,role_ID) VALUES");		sbsql.append(" (").append(groupMember.getUserID())			.append(",").append(groupMember.getGroupID())			.append(",").append(groupMember.getMemberID())			.append(",").append(groupMember.getRole())			.append(");");		db.execsql(sbsql.toString());	}	db.setTransactionSuccessful();	db.endTransaction();}

尽量别用下面的sql语法,在部分机型上面会报错。(小米、三星S3)。上面的写法已经可以满足需要了……

INSERT INTO table(column1,column2) VALUES(val1,val2),(val1,val2)

批量新增的写法没什么好解释的了,下面分享下批量修改。

二、批量修改

需求的出现:比如存在N个聊天圈子,圈子中有N个成员。每次进入圈子的时候后台线程下载圈子成员最新数据,并更新数据库。这时候存在三个表:圈子,圈子-成员关系表,用户表。

用户表是所有圈子的用户,保存的时候需要判断是否存在,存在就新增,否则修改部分数据。(因为用户带有详细资料,而圈子成员返回的只有名字、账号、头像三个字段,不能用上面的方法先删除所有数据,然后批量新增

sql关键写法如下(重点是sqliteDatabase.insertWithOnConflict的用法):

public voID insertOrReplace(List<GroupMember> ListMember) {	sqliteDatabase db = super.getDatabase();	db.beginTransaction();	for (int i = 0; i < ListMember.size(); i++) {		BaseUserInfo baseUserInfo = ListMember.get(i).getBaseUserInfo();		ContentValues cv = new ContentValues();		cv.put("user_ID",baseUserInfo.getUserID());		cv.put("name",baseUserInfo.getname());		cv.put("logo",baseUserInfo.getlogo());				// 生成的sql是 INSERT INTRO OR REPLACE INTO 这样的 (如果存在就替换存在的字段值. 存在的判断标准是主键冲突,这里的主键是userID). 下面会介绍这个地方的方法		db.insertWithOnConflict(table,null,cv,sqliteDatabase.CONFliCT_REPLACE);	}	db.setTransactionSuccessful();	db.endTransaction();}

关键的一个地方:

insertWithOnConflict(String table,String nullColumnHack,ContentValues initialValues,int conflictAlgorithm)

部分参数介绍(忽略参数table和initialValues了,这个大家都知道吧 - -):

1) nullColumnHack当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行),为了防止这种情况,我们要在这里指定一个列名,到时候如果发现将要插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入。(实际开发中一般设置为null就好。)

比如:如果values为空,最后生成的sql大概是"INSERT INTO table"这样的,那么这是一个错误的sql,肯定插入失败。但是如果指定了nullColumnHack,最终会生成sql"INSERT INTO table("+nullColumnHack+")" VALUES (null)"; 这样会插入一行没数据的行,但是sql不会报错了。

实际androID源码如下:

public long insertWithOnConflict(String table,int conflictAlgorithm) {	acquireReference();	try {		StringBuilder sql = new StringBuilder();		sql.append("INSERT");		sql.append(CONFliCT_VALUES[conflictAlgorithm]);		// 注意这里,等下介绍		sql.append(" INTO ");		sql.append(table);		sql.append('(');		Object[] bindArgs = null;		int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0;		if (size > 0) {			bindArgs = new Object[size];			int i = 0;			for (String colname : initialValues.keySet()) {				sql.append((i > 0) ? "," : "");				sql.append(colname);				bindArgs[i++] = initialValues.get(colname);			}			sql.append(')');			sql.append(" VALUES (");			for (i = 0; i < size; i++) {				sql.append((i > 0) ? ",?" : "?");			}		} else {			sql.append(nullColumnHack + ") VALUES (NulL");		}		sql.append(')');		sqliteStatement statement = new sqliteStatement(this,sql.toString(),bindArgs);		try {			return statement.executeInsert();		} finally {			statement.close();		}	} finally {		releaseReference();	}}


2) conflictAlgorithm

该参数是一个int值,上面源码中也用到了(CONFliCT_VALUES[conflictAlgorithm]),那么CONFliCT_VALUES的值是什么?AndroID源码中如下:

public static final int CONFliCT_RolLBACK = 1;public static final int CONFliCT_ABORT = 2;public static final int CONFliCT_FAIL = 3;public static final int CONFliCT_IGnorE = 4;public static final int CONFliCT_REPLACE = 5;public static final int CONFliCT_NONE = 0;private static final String[] CONFliCT_VALUES = new String[]{""," OR RolLBACK "," OR ABORT "," OR FAIL "," OR IGnorE "," OR REPLACE "};

好了,结合方法insertWithOnConflict的源码一起就明白了,当你指定了该参数,最终得到的sql是 "INSERT OR REPLACE INTO table(column1,column2...) VALUES(val1,val2...)" 这样的格式……

这样就解决了最开始说的需求产生场景中遇到了的性能瓶颈。


分享出来,希望对有需要的人有帮助。

总结

以上是内存溢出为你收集整理的SQLite 大数据量 新增 / 修改 提升效率的办法全部内容,希望文章能够帮你解决SQLite 大数据量 新增 / 修改 提升效率的办法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1180466.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存