想了几种方法:
1.将所有符合条件的对象集合都查出来,在代码里做随机。
2.先查出所有符合条件的id,再代码随机需要抽查数量的id,再 到数据库 中 in。
3.利用order by rand() limit ,随机出需要抽查数量的id,再到数据库中 in
条件过滤后,大概15万条数据,测试,第3种方法相对快,但是抽查数量到 7k, 8k, 1w 时候,第2种会稍微快点。
知乎上:https://www.zhihu.com/question/20151242 建议用第2种。
可能测试不够充分,待继续测试。。。
public List<OpenMsgDo> getMsgList(QueryOpenMsgBean queryReq) { List<OpenMsgDo> exportList = new ArrayList<>();
transform(queryReq);
int randomSearchNum = Integer.parseInt(queryReq.getRandomSearchNum()); log.info("查询的表名queryTableName=" + /*queryReq.getQueryTableName() + ", 符合查询条件的短信数量="
+ allIdsSize + */", 页面抽查的短信数量=" + randomSearchNum); //1.order by rand() limit 方式随机获取 id,再in
// long startTime2 = System.currentTimeMillis(); //开始测试时间
List<Integer> randomIdsList2 = openMsgMapper.getRandomMsgIdsList(queryReq);
if (randomIdsList2.size() > 0) {
exportList = openMsgMapper.getMsgListByIds(queryReq.getQueryTableName(),
randomIdsList2);
}
// long endTime2 = System.currentTimeMillis(); //获取结束时间
// System.out.println("【【rand id 再in 方式 获取短信集合耗时: " + (double)(endTime2 - startTime2) / 1000 + "s】】");
return exportList; /*
* 2.查出所有id,再随机id进去 ,in
* long startTime = System.currentTimeMillis(); //开始测试时间
List<Integer> allIdsList = openMsgMapper.getMsgIdsList(queryReq);
int allIdsSize = allIdsList.size();
if (allIdsSize > 0) {
//随机抽取id
List<Integer> randomIdsList = new ArrayList<>();
log.info("查询的表名queryTableName=" + queryReq.getQueryTableName() + ", 符合查询条件的短信数量="
+ allIdsSize + ", 页面抽查的短信数量=" + randomSearchNum);
int max = allIdsSize;
if (randomSearchNum < allIdsSize) {
//随机抽取,再导出
for (int i = 0; i < randomSearchNum; i++) {
int num = random.nextInt(max - i);//[0,max-i)
randomIdsList.add(allIdsList.get(num));
allIdsList.remove(num); //获得后去除,防止重复
}
log.info("实际随机抽取的短信数量=" + randomIdsList.size());
} else {
randomIdsList = allIdsList;
}
exportList = openMsgMapper.getMsgListByIds(queryReq.getQueryTableName(), randomIdsList);
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("【【获取所有id,随机抽取,再in 方式 获取短信集合耗时: " + (double)(endTime - startTime)/1000 + "s】】");
}*/ /*
* 3.短信集合都查出来,再随机
* transform(queryReq);
List<OpenMsgDo> list = openMsgMapper.getMsgList(queryReq);
int listSize = list.size();
int randomSearchNum = Integer.parseInt(queryReq.getRandomSearchNum());
log.info("查询的表名queryTableName=" + queryReq.getQueryTableName() + ", 符合查询条件的短信数量=" + listSize
+ ", 页面抽查的短信数量=" + randomSearchNum); int max = listSize;
List<OpenMsgDo> exportList = new ArrayList<>();
if (randomSearchNum < listSize) {
//随机抽取,再导出
Set<OpenMsgDo> set = new TreeSet<>();
for (int i = 0; i < randomSearchNum; i++) {
int num = random.nextInt(max - i);//[0,max-i)
set.add(list.get(num));
list.remove(num); //获得后去除,防止重复
}
log.info("实际随机抽取的短信数量=" + set.size());
exportList.addAll(set);
} else {
exportList = list;
} return exportList;*/
}