想了几种方法:
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;*/ }