最代码官方
2015-12-12 19:56:20
原证精
最代码网站用户私信列表采用mysql union查询优化为Redis查询的经验和相关代码片段分享
由于用户和私信的数据量逐渐增加,查询用户和其他用户的私信合并排重排序的sql语法给mysql带来了很大的压力,springdata jpa的hql查询语法如下:
select id from (select id,target_id,case when user_id=?1 and type=?2 then 'sender' else 'receiver' end flag from javaniu_post where user_id=?1 and type=?2 union select id,user_id,case when user_id=?1 then 'sender' else 'receiver' end flag from javaniu_post where target_id=?1 and type=?2 order by id desc) as ret group by target_id order by id desc
在mysql的slow查询中经常会出现10s以上的记录:
mysql查询性能的瓶颈在于某个用户和其他用户之间交互越多,发送私信越多,mysql union查询参与运算的集合数据量会越大,性能也会越来越低。
数据变化如下:
1.用户A发给用户B生成私信1
用户A->用户B->私信1
2.用户A发给用户C生成私信2
用户A->用户C->私信2
3.用户A发给用户E生成私信3
用户A->用户E->私信3
4.查询用户A的私信列表
私信3,私信2,私信1
5.用户B发给用户A生成私信4
用户B->用户A->私信4
6.查询用户A的私信列表
私信4,私信3,私信2
私信1因为有最新数据私信4的存在,所以不会返回。
所以迫切需要引入新的技术来解决该查询的性能瓶颈,想到了流行的redis技术,于是修改设计如下:
模拟发私信的数据结构如下
127.0.0.1:6379> zadd uid1 1 2 (integer) 1 127.0.0.1:6379> zadd uid1 2 3 (integer) 1 127.0.0.1:6379> zadd uid1 3 5 (integer) 1 127.0.0.1:6379> zrevrange uid1 0 -1 1) "5" 2) "3" 3) "2" 127.0.0.1:6379> zrevrange uid1 0 -1 withscores 1) "5" 2) "3" 3) "3" 4) "2" 5) "2" 6) "1" 127.0.0.1:6379> zadd uid1 4 2 (integer) 0 127.0.0.1:6379> zrevrange uid1 0 -1 withscores 1) "2" 2) "4" 3) "5" 4) "3" 5) "3" 6) "2" 127.0.0.1:6379>
注意:把私信id做为score来做排序
相关代码片段如下:
删除或添加私信时:
String uid = t.getUserId() + ""; String type = ModuleConstants.POST_TYPE_MESSAGE + ""; String tgid = t.getTargetId() + ""; long id = t.getId(); long time = t.getCreateTime().getTime(); String po_uid_tp_tgid = String.format( RedisConstants.POST_USERID_TYPE_TARGETID, uid, type, tgid); // from uid String po_uid_tp = String.format(RedisConstants.POST_USERID_TYPE, uid, type); // to uid String po_tgid_tp = String.format(RedisConstants.POST_USERID_TYPE, tgid, type); if (t.getStatus() == ModuleConstants.MODULE_STATUS_DELETED) {// 删除私信同时要删除redis zsetOps.remove(po_uid_tp_tgid, id + ""); zsetOps.remove(po_uid_tp, tgid); zsetOps.remove(po_tgid_tp, uid); } else { zsetOps.add(po_uid_tp_tgid, id + "", time); zsetOps.add(po_uid_tp, tgid, id); zsetOps.add(po_tgid_tp, uid, id); }
查询用户的私信时:
String uid = userId + ""; String tp = ModuleConstants.POST_TYPE_MESSAGE + ""; String po_uid_tp = String.format(RedisConstants.POST_USERID_TYPE, uid, tp); int total = zsetOps.zCard(po_uid_tp).intValue(); int ps = total / count + (total % count > 0 ? 1 : 0); if (page > ps) { page = ps; } int start = (page - 1) * count; int end = page * count - 1; Set<TypedTuple<String>> _ids = zsetOps.reverseRangeWithScores( po_uid_tp, start, end); List<Long> ids = new ArrayList<Long>(); Iterator<TypedTuple<String>> iterator = _ids.iterator(); while (iterator.hasNext()) { TypedTuple<String> _id = iterator.next(); long id = _id.getScore().longValue(); ids.add(id); } List<Post> ts = (List<Post>) findAllByIds(ids); Pageable pageable = new PageRequest(page - 1, count); Page<Post> _page = new PageImpl<Post>(ts, pageable, total); initBeans(_page.getContent());
redis查询最代码官方,id=1的所有私信列表,和mysql union运算的结果完全一致,但是性能可是天壤之别:
相关资料和代码:
猜你喜欢
请下载代码后再发表评论



yanxiaoai LV6
1月24日
zz1230012300 LV10
2022年8月29日
locklock LV2
2022年6月23日
2500743843
2022年6月1日
暂无贡献等级
12345670
2022年4月10日
暂无贡献等级
itcaizhe LV8
2021年10月28日
glqywy1 LV4
2021年10月25日
廖业贵 LV13
2021年6月28日
2840820049 LV9
2021年6月9日
ssm_er LV4
2021年4月23日