记录一次Java代码数据优化的经历,优化包括insert update select


下面是 业务背景

介绍一下业务背景 前台传过来id集合a,循环集合a,通过id前一部分模糊查询对应的数据集b,循环b: 1 判断逻辑正确的集合进行赋值(字段值相同),然后更新。2 创建实体类,保存。注:下面代码是模仿业务的,不是纯代码

//最初版本执行时间30分钟
//前台传过来id集合
List<String>  uuids = (前台传过来的数据集);
for(String s : uuids) {
	//like查询匹配的数据集,
	List<Obj> objs = select * from tablename1 where id like s+"%";
	for(Obj o : objs) {
		if((o.xx).equals(xx)) {
			o.seta(a);
			o.setb(b);
			update(o);
			//添加实体
			Qq q = new qq();
			q.setx(xx);
			...
			save(q);
		}
	}
	
}

删除模糊查询

模糊查询效率低下,不走索引。遂删除模糊查询,用精确查询替代。

//原查询语句
List<Obj> objs = select * from tablename1 where id like s+"%";
//现查询语句
Obj o1 = select * from tablename1 where id = s+"a";
Obj o2 = select * from tablename1 where id = s+"b";
Obj o3 = select * from tablename1 where id = s+"c";

执行时间有所提升,但是还是很慢。。。

MySQL索引

通过把查询的id设置成唯一索引,提升了查询速度,优化了代码。

但是索引的功能和实现还是存在于表面,需要继续努力学习原理!

复习一下索引知识:

存储方式区分
1) B-树索引
B-树索引又称为 BTREE 索引,目前大部分的索引都是采用 B-树索引来存储的。
2) 哈希索引
哈希(Hash)一般翻译为“散列”,也有直接音译成“哈希”的,就是把任意长度的输入(又叫作预映射,pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。哈希索引也称为散列索引或 HASH 索引。MySQL 目前仅有 MEMORY 存储引擎和 HEAP 存储引擎支持这类索引。其中,MEMORY 存储引擎可以支持 B-树索引和 HASH 索引,且将 HASH 当成默认索引。
逻辑区分
1) 普通索引
普通索引是 MySQL 中最基本的索引类型,它没有任何限制,唯一任务就是加快系统对数据的访问速度。普通索引允许在定义索引的列中插入重复值和空值。创建普通索引时,通常使用的关键字是 INDEX 或 KEY。
2) 唯一索引
唯一索引与普通索引类似,不同的是创建唯一性索引的目的不是为了提高访问速度,而是为了避免数据出现重复。唯一索引列的值必须唯一,允许有空值。如果是组合索引,则列值的组合必须唯一。创建唯一索引通常使用 UNIQUE 关键字。
3) 主键索引
顾名思义,主键索引就是专门为主键字段创建的索引,也属于索引的一种。主键索引是一种特殊的唯一索引,不允许值重复或者值为空。创建主键索引通常使用 PRIMARY KEY 关键字。不能使用 CREATE INDEX 语句创建主键索引。
4) 空间索引
空间索引是对空间数据类型的字段建立的索引,使用 SPATIAL 关键字进行扩展。创建空间索引的列必须将其声明为 NOT NULL,空间索引只能在存储引擎为 MyISAM 的表中创建。空间索引主要用于地理空间数据类型 GEOMETRY。对于初学者来说,这类索引很少会用到。
5) 全文索引
全文索引主要用来查找文本中的关键字,只能在 CHAR、VARCHAR 或 TEXT 类型的列上创建。在 MySQL 中只有 MyISAM 存储引擎支持全文索引。全文索引允许在索引列中插入重复值和空值。不过对于大容量的数据表,生成全文索引非常消耗时间和硬盘空间。创建全文索引使用 FULLTEXT 关键字。
实际使用区分
1)单列索引
单列索引就是索引只包含原表的一个列。在表中的单个字段上创建索引,单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。
2)多列索引
组合索引也称为复合索引或多列索引。相对于单列索引来说,组合索引是将原表的多个列共同组成一个索引。多列索引是在表的多个字段上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询。但是,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用。

引用链接

优化insert语句

原来的insert是每循环一次,插入一次。所以需要执行n次insert语句,数据量大的时候,速度明显慢了。
改成先存入集合在执行insert语句,效率提升很大。代码如下:

// 原代码
for(){
	//添加实体
	Qq q = new qq();
	q.setx(xx);
	...
	save(q);
}

//优化后代码
list<Obj> lists = new ArrayList<>();
for(){
	//添加实体
	Qq q = new qq();
	q.setx(xx);
	...
	lists.add(lists);
}
insert(lists);

系统中的insert语句

执行多次n次insert和执行一次insert相差的时间是巨大的,通过修改插入语句,将执行时间降低到了10分钟。

优化update语句

执行时间已经降低很多了(相对于第一次(手动滑稽=_+))。但是客户还是不满足,没办法继续优化。和同事讨论发现每次更新的数据都是相同的,这里可以优化,优化方案类似于insert,但是有所不同。
优化思路:for循环n次 update执行n次,如果也让它执行一次就可以,那效率一定飕飕的!正好业务给力,每次存储的数据是相同的,只是id不同,所以想到先用集合存储id集合,最后执行一次update语句。代码如下:

// 原代码
for(){
	//修改实体
	o.seta(a);
	o.setb(b);
	update(o);
}

//优化后代码
list<Obj> lists = new ArrayList<>();
for(){
	lists.add(lists);
}
update set a = a, b = b where id in lists;

系统中的update语句

通过多次修改和优化,终于将代码执行时间控制在1分钟左右。作者的能力暂时到这里了,如果有大佬还有更好的方案,欢迎指正!!!
PS:有时候客户不逼自己一把,自己不知道可以进步的空间有多大!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值