本文共 8133 字,大约阅读时间需要 27 分钟。
I look at you
You look at me 两个功能:a.我可以查看谁 look at 了我 b.查看我look at 了谁。 历史设计: MySQL数据库分了100张表,当 I look at you , 我的表里存一条数据: I look at you 状态为0 ,you的 表里插一条数据 我被你look at 状态为1 。 当 You look at me ,you的表里插入 状态为0 的数据,我的表里插入状态为1 的数据,即:一方look at 插入双方的数据。比如: 我的id 为111111 你的id为222222,当我look at 你的时候,表的情况是这样的
我的表 LOOK_AT_11
你的表 LOOK_AT_22
当你也look at 了我 , 我也look at 了你的时候,表的情况是这样的。
我的表 LOOK_AT_11
你的表 LOOK_AT_22
需求2:现在有新需求,当我look at 了你,你也look at 了我的时候,说明俩人看对眼儿了, 产品经理要把看对眼儿的人挑出来展示给用户。在当前设计的基础上,我们新增了一个状态,STATUS=2 为对眼儿,当 我俩互相 look at 的时候,插入一条STATUS=2 的数据,由于我查询对眼儿用户的时候,需要按照UPDATE_TIME排序查询,所以上线之后数据是这样的。
(我的id:333333 , 你的id:444444,我俩互相look at)我的表 LOOK_AT_33
你的表 LOOK_AT_22
那么问题来了,老数据该怎么办?
我们需要写个job,来给历史互相look at 的用户插入一条STATUS=2 的对眼儿数据。READY===========================GO!!!
1.循环100张表,每次循环,在每张表里取出所有我被你 look at 的beLookEdAtlist 和 我look at 你的iLookAtList.
2.将beLookEdAtlist 转成map ,结构:Map<myId,youIdList> ,目的:用来判断是否有look我的人,有则继续判断,没有则下一轮循环,用于减少判断。
3.循环beLookEdAtlist 和 iLookAtList ,找出myid 相等,youId相等的数据组装。 插入数据
public void execute() { for (int table = 0; table<100; table++) { //param 控制第几张表 String dbTable = "LOOK_AT" + table; Integer lookType = LookAtEnum.ILOOKATYOU.getType(); ListiLookAtList = Dao.findByLookAtType(dbTable, lookType); if (CollectionUtils.isEmpty(iLookAtList)) { return; } Integer beLookType = LookActionEnum.BE_LookED.getType(); List beLookEdAtlist = Dao.findByLookAtType(dbTable, beLookType); if (CollectionUtils.isEmpty(beLookEdAtlist )) { return; } Map > map = new HashMap<>(); beLookEdAtlist.forEach(lookAtEmpty -> { if (map.get(lookAtEmpty.getUserId()) == null) { List list = new ArrayList<>(); list.add(lookAtEmpty.getOtherUserId()); map.put(lookAtEmpty.getUserId(), list); } else { List existList = map.get(lookAtEmpty.getUserId()); existList.add(lookAtEmpty.getOtherUserId()); map.put(lookAtEmpty.getUserId(), existList); } }); List resList = new ArrayList<>(); for (LookAtEmpty lookAtEmpty : iLookAtList) { List beLookEdAtUserIds = map.get(lookAtEmpty.getUserId()); if (CollectionUtils.isEmpty(beLookEdAtUserIds) || !beLookEdAtUserIds.contains(lookAtEmpty.getOtherUserId())) { continue; } for (LookAtEmpty beLookedAtEmpty : beLookEdAtlist ) { if (beLookedAtEmpty.getUserId() == beLookUser.getUserId() && beLookedAtEmpty.getOtherUserId() == beLookedAtEmpty.getOtherUserId()) { Date updateTime = beLookUser.getCreateTime().before(beLookedAtEmpty.getCreateTime()) ? beLookedAtEmpty.getCreateTime() : beLookUser.getCreateTime(); beLookUser.setCreateTime(updateTime); beLookUser.setUpdateTime(updateTime); resList.add(beLookUser); } } } } }
老大看了我的代码后说:“其实可以分页”
我说:“不能,因为关系可能存在于下一页” 老大说:“可以分页…” 我说:“不能!” 老大说:“可以分页……” 我说:“不能!!”我还是让老大把话说完了 ,才有了第二版代码。
1.循环100张表,在每张表中用数据库limit分页取出我look at 你的数据,全部取出到内存里,用map 存储,key为 myId-youId , value 为Createtime。因为我需要在我look at 你 和你look at 我两条数据里取出Createtime 最大的,放到对眼儿数据的Createtime 和 UpdateTime里。
2.然后分页取出我被你look at 的数据,在map中找有没有Createtime ,有则说明两者有过对眼儿,需要插入数据
3.插入数据
public void execute() { int pageSize = 500; int pageNum = 0 ; for (int table = 0; table<100; table++){ String dbTable ="LOOK_AT"+table; MaplookAtMap = new HashMap<>(); for (int i =0;i<= 400;i++){ List lookAtList = Dao.findByLookAtType(dbTable,LookAtEnum.ILOOKATYOU.getType(),pageNum*pageSize,pageSize); if (CollectionUtils.isEmpty(lookAtList) ){ break; } for (LookAtEmpty lookAtEmpty :lookAtList){ String key = lookAtEmpty.getMyId()+"-"+lookAtEmpty.getYouId(); lookAtMap.put(key,lookAtEmpty.getCreateTime()); } if( lookAtList.size() idResList = new ArrayList<>(); int res=0; int pageNum1 =0; for (int i =0;i<=400;i++){ List beLookList = Dao.findByLookAtType(dbTable,LookAtEnum.IBELOOKEDBYYOU.getType(),pageNum1*pageSize,pageSize); if (CollectionUtils.isEmpty(beLookList)){ break; } for (LookAtEmpty lookAtEmpty :beLookList){ String key = lookAtEmpty.getMyId()+"-"+lookAtEmpty.getYouId(); if (lookAtMap.get(key) !=null){ Date lookDate = lookAtMap.get(key); Date updateTime = lookAtEmpty.getCreateTime().before(lookDate) ? lookDate:userRelation.getCreateTime(); LookAtEmpty u = new LookAtEmpty( lookAtEmpty.getMyId(), lookAtEmpty.getYouId(), LookAtEnum.DUIYANER.getType(), updateTime, updateTime); idResList.add(u); } } if (CollectionUtils.isNotEmpty(idResList)){ res += Dao.insertLookAtEmptyList(dbTable,idResList); } idResList.clear(); pageNum1++; if (beLookList.size()
老大看过之后又给了几条建议:
1.for循环里已经有了终止条件:if(lookAtList.size() < pageSize){ break;}
所以不需要在for循环里限定400
2.findByLookAtType 方法的查询分页,用的是MySQL的limit,limit在分页越往后,效率就越低,所以不如以时间倒序查询,每次记录最后一条数据的createtime,下次查询<createtime的数据即可,createtime加索引。
public void execute() { int pageSize = 500; for (int table = 0; table<100; table++){ String dbTable ="LOOK_AT"+table; MaplookAtMap = new HashMap<>(); Date iLookCreateTime = new Date(); for (int i =0;;i++){ List lookAtList = Dao.findByTime(dbTable,LookAtEnum.ILOOKATYOU.getType(),iLookCreateTime,pageSize); if (CollectionUtils.isEmpty(lookAtList) ){ break; } for (LookAtEmpty lookAtEmpty :lookAtList){ String key = lookAtEmpty.getMyId()+"-"+lookAtEmpty.getYouId(); lookAtMap.put(key,lookAtEmpty.getCreateTime()); } if( lookAtList.size() idResList = new ArrayList<>(); int res=0; int pageNum1 =0; Date beLookDateTime = new Date(); for (int i =0;;i++){ List beLookList = Dao.findByTime(dbTable,LookAtEnum.IBELOOKEDBYYOU.getType(),beLookDateTime,pageSize); if (CollectionUtils.isEmpty(beLookList)){ break; } for (LookAtEmpty lookAtEmpty :beLookList){ String key = lookAtEmpty.getMyId()+"-"+lookAtEmpty.getYouId(); Date lookDate = lookAtMap.get(key); if (lookDate !=null){ Date updateTime = lookAtEmpty.getCreateTime().before(lookDate) ? lookDate:userRelation.getCreateTime(); LookAtEmpty u = new LookAtEmpty( lookAtEmpty.getMyId(), lookAtEmpty.getYouId(), LookAtEnum.DUIYANER.getType(), updateTime, updateTime); idResList.add(u); } } if (CollectionUtils.isNotEmpty(idResList)){ res += Dao.insertLookAtEmptyList(dbTable,idResList); } beLookDateTime = beLookList.get(beLookList.size()-1).getCreateTime(); idResList.clear(); if (beLookList.size()
如此,用数据结构提高了不少效率,有趣吧!
转载地址:http://ptgjx.baihongyu.com/