mysql通讯数据包大小,默认1M这么小的,1024byte, show variables like '%max_allowed_packet%'
67108864=65536*1024=64*1024*1024=64M,
一个bigint就是8byte,1000条是,8000byte,约等于8M,我看我们系统代码经常5000一次select出来的报表之类的;
常用的sql分批查询代码:
方式一:
Listlablelists = memberLevelChangeRecordMapper.selectLabelN(map); Integer totalCount= lablelists.size(); if (totalCount <= 0){ LogWriter.info("【DealMembershipLabelService||dealLevelPurchaseLabel】totalCount="+totalCount); labelInfo.setMemberCount(0); return; } // PAGE_NUM=500,分批,update 一次user表,修改标签值字段 Integer totalPages = totalCount % PAGE_NUM == 0 ? totalCount / PAGE_NUM : (totalCount / PAGE_NUM + 1); Integer num = 0; int i; for (i = 0; i < totalPages-1; i++) { List batchLists = lablelists.subList(i * PAGE_NUM, (i * PAGE_NUM + PAGE_NUM)); map.put("openIds", batchLists); map.put("rmk2", labelInfo.getLabelValue()); num += tJfzwAppUserInfoMapper.initLabelM(map); } List batchLists2 = lablelists.subList(i * PAGE_NUM, totalCount); map.put("openIds", batchLists2); map.put("rmk2", labelInfo.getLabelValue()); num += tJfzwAppUserInfoMapper.initLabelM(map); //clear ,改变了数组的size ,被引用的元素减少了,提前clear导致subList(取得不准确,变量用完后再clear batchLists2.clear(); batchLists2 = null; lablelists.clear(); lablelists = null; LogWriter.info(labelInfo.getLabelValue()+"标签人数: num:"+ num+"totalCount:"+totalCount);
方式二:
LogWriter.info("updateUserExpTime----start----");
long startTime=System.currentTimeMillis();
List userInfos = appUserInfoMapper.queryList(po);
LogWriter.info("updateUserExpTime----start----修改会员等级userInfos,用户数目" + userInfos.size()+"...po.getMerchantCode() is :"+po.getMerchantCode());
if (userInfos.isEmpty() ){ return; }
Map map = new HashMap<>();
map.put("mchntCd", po.getMerchantCode());
// 商户改等级有效期配置的话,也是从用户等级变动的那天算
// 这里计算,差值,新旧配置的有效期之间的差值,就是变化值
// map.put("expTime", DateUtils.getSpecifiedDay(nowTime, "yyyy-MM-dd", level.getExpDays().intValue()));
int distanceDay = currentExpDays-oldExpDays;
map.put("nowTime",new Date());
map.put("nowDate",DateUtils.getSpecifiedDay(DateUtils.getCurrentDate(), "yyyy-MM-dd", distanceDay));
map.put("distanceDay", distanceDay);
// map.put("openIdList", userInfos);
map.put("appUserTableName", Constants.APP_USER_TABLE_NAME+mchntInfoService.getUserTableSuffix(po.getMerchantCode()));
int result=0;
// sql批量更新 ,一条sql语句来批量更新所有数据
// 可以在一次数据库连接中更新所有数据,避免了频繁数据库建立和断开连接的开销,可以很大程度的提高数据更新效率。
// 但是这样的问题是如果这个过程中更新出错,将很难知道具体是哪个数据出错
// 因此通常的使用的方案是进行折中,也就是一次批量更新一部分(分页进行更新,比如说一共有1000条数据,一次更新100条)
if (userInfos.size() <= 500) {
map.put("openIdList", userInfos);
result = memberExperienceMapper.updateExpTimeAdd(map);
//add by Aaron 补充会员经验过期字段
appUserInfoMapper.updateUserLevelExpDateByMemberListDate(map);
//如果list数目过大,需要用完后立即释放清空list存储空间,便于gc ,是局部变量,可以立即回收
userInfos.clear();
userInfos=null;
LogWriter.info("updateUserExpTime----end--<= 500--修改会员等级userInfos,用户result数目" + result);
} else {
int pageSize = 500;
int pageNum;
for (pageNum = 1; pageNum <= userInfos.size() / pageSize; pageNum++) {
LogWriter.info("分批list,每500条分一批");
List batchLists = userInfos.subList((pageNum - 1) * pageSize, ((pageNum - 1) * pageSize + pageSize));
map.put("openIdList", batchLists);
result += memberExperienceMapper.updateExpTimeAdd(map);
//add by Aaron 补充会员经验过期字段
appUserInfoMapper.updateUserLevelExpDateByMemberListDate(map);
}
List batchLists2 = userInfos.subList((pageNum - 1) * pageSize, userInfos.size());
if(batchLists2.size()>0) {
map.put("openIdList", batchLists2);
result += memberExperienceMapper.updateExpTimeAdd(map);
//add by Aaron 补充会员经验过期字段
appUserInfoMapper.updateUserLevelExpDateByMemberListDate(map);
//clear ,改变了数组的size ,被引用的元素减少了,提前clear导致subList(取得不准确,变量用完后再clear
batchLists2.clear();
batchLists2 = null;
}
userInfos.clear();
userInfos=null;
LogWriter.info("updateUserExpTime----end-->500--修改会员等级userInfos,用户result数目" + result+"...po.getMerchantCode() is:"+po.getMerchantCode());
方式三:
long startTime=System.currentTimeMillis();
LogWriter.info("labelInfo :"+ JSONObject.toJSONString(labelInfo));
Integer totalCount = tJfzwUserInfoMapper.selectLabelLTotal(map);
if (totalCount <= 0){
LogWriter.info("【DealMembershipLabelService||dealConsumeFrequencyLabel】totalCount="+totalCount);
labelInfo.setMemberCount(0);
return;
}
Integer totalPages = totalCount % PAGE_NUM == 0 ? totalCount / PAGE_NUM : (totalCount / PAGE_NUM + 1);
Integer num = 0;
map.put("pageSize",PAGE_NUM);
for (int i = 0; i < totalPages; i++) {
map.put("pageStartNum", i * PAGE_NUM); // 分页limit起始值
List lablelists = tJfzwUserInfoMapper.selectLabelL(map);
if (lablelists == null || lablelists.isEmpty() ){ break; }
map.put("openIds",lablelists);
map.put("rmk2",labelInfo.getLabelValue());
num += tJfzwAppUserInfoMapper.initLabelM(map);
//如果list数目过大,需要用完后立即释放清空list存储空间,便于gc ,是局部变量,可以立即回收
lablelists.clear();
lablelists=null;
}
LogWriter.info(labelInfo.getLabelValue()+"标签人数: num:"+ num+"totalCount:"+totalCount);
labelInfo.setMemberCount(num);
long endTime=System.currentTimeMillis();
LogWriter.info("【DealMembershipLabelService||dealConsumeFrequencyLabel】========程序耗时:"+(endTime-startTime)+"ms");
这三种方式,因为for循环计算的执行次数是不一样的。
第三种方式,是先批量查询出来,然后批量修改,



