有一种业务场景 类似QQ空间 用户能发 日志和 说说,但是 之前的设计 是二个表 ,一个表存日志,一个表存说说,并且很多字段不一样,但是有一个字段相同 create_time ,在用户主页按照创建时间降序同时展示 日志+ 说说,
这个时候就碰到一个分页的问题,假设每次请求 10条数据
刚开始的想法是:方案一
select * from t_日志表 order by create_time desc limit 0,10
select * from t_说说表 order by create_time desc limit 0,10
二个表返回的一共20条数据放入一个数组,然后再按照时间排序
如果要查 第 91 条到 100 条
select * from t_日志表 order by create_time desc limit 9,10
select * from t_说说表 order by create_time desc limit 9,10
再合并处理 但是这样肯定不行(细节原因就不提了),
然后换成如下处理:方案二
select * from t_日志表 order by create_time desc limit 100
select * from t_说说表 order by create_time desc limit 100
从这合并排序这200条数据,然后取出 91~100 条,但是查询一旦越往后,速度越慢。
方案三
后面想到了一种比较可以的方案 查询时携带 createTime 字段。
第一次查询createTime 就为空 还是跟以前一样处理,返回 20 条 ,然后合并排序取出前面 10 条,此时第10 条 数据的 createTime 是 这十条中最小的,
第2次查询的时候 带上次查询createTime , 查询的数据的 createTime 肯定比这个 createTime 要小
(这里假设查询一直只往后查询,前面查询的数据都保存在客户端了 )
select * from t_日志表 where create_time< createTime order by create_time desc limit 0,10
select * from t_日志表 where create_time< createTime order by create_time desc limit 0,10
从这20条数据中 合并再排序 取出 前10条,这样处理每次最多返回 20条,
客户端需要的数据总数为,
select count(*) from t_日志表 + select count(*) from t_说说表
备注( 当然正常情况 是可能出现 往前查询 的,其实 处理方式 也是类似 ,查完第 N 页后
如果需要查询N-1 页 需要 给后台 N 页的 第一条数据的 createTime 然后查询比 createTime 大的
如果需要查询N+1 页 需要 给后台 N 页的 最后一条数据的 createTime 然后查询比 createTime 小的,
这里需要客户端传入一个状态了 来决定 是往前还是往后查。
下面附上一段代码 二个不同类型数组,如何合并排序
List<Object> objectList = new ArrayList<>(说说数组.size()+日志数组.size());
objectList.addAll(说说数组);
objectList.addAll(日志数组);
objectList.sort((obj1,obj2) ->{
Date createTime1 = null;
Date createTime2 = null;
try {
Field field1 = obj1.getClass().getDeclaredField("createTime");
field1.setAccessible(true);
onlineTime1 = (Date)field1.get(obj1);
Field field2 = obj2.getClass().getDeclaredField("createTime");
field2.setAccessible(true);
onlineTime2 = (Date)field2.get(obj2);
} catch (Exception e) {
e.printStackTrace();
}
boolean after = createTime1.after(createTime2);
return after ? 1 : -1;
});