1、rpc批量查詢
private List<DTO> query(String code, Integer type) {
List<DTO> resultList = new ArrayList<>();
List<DTO> skuList;
//01.構(gòu)造req
Req request = buildTRequest(code, type);
Response response;
int fetchedCount = 0;
int maxCycle = 1;
boolean needMoreFetch = true;
while (maxCycle <= 1000) {
maxCycle++;
try {
response = skuGateway.query(request);
} catch (Exception e) {
throw new GatewayException(1,
String.format("獲取sku失敗 code:[%s]", code), e);
}
skuList = response.getData();
if (CollectionUtils.isNotEmpty(skuList)) {
resultList.addAll(skuList);
fetchedCount += skuList.size();
}
if (total <= fetchedCount) {
needMoreFetch = false;
} else {
request.setOffset(fetchedCount);
}
}
return resultList;
}
2、200、200條查詢db數(shù)據(jù)
- eg1
private void query(Request request) {
int page = 1;
List<DO> dOList = query(request, page);
while (CollectionUtils.isNotEmpty(dOList) && page <= 1000) {//一次200,循環(huán)1000次,就是20w的數(shù)據(jù)量,肯定夠了
//處理數(shù)據(jù)
judgeSameTask(dOList);
if (200 > dOList.size()) {
break;
}
page++;
dOList = query(request, page);
}
}
- eg2
private List<Info> batchQuery(Request request) {
List<Info> result = new ArrayList<>();
int page = 1;
List<Info> infos = query(request, page);
while (CollectionUtils.isNotEmpty(infos) && page <= 1000) {//一次200,循環(huán)1000次,就是20w的數(shù)據(jù)量,肯定夠了
result.addAll(infos);
if (200 > infos.size()) {
break;
}
page++;
infos = query(request, page);
}
return totalSkuStockList;
}
private List<ReturnPlanTaskDO> query(Request request, int page) {
//01.構(gòu)建查詢條件
XxxDOExample example = buildDOExample();
//02.分頁參數(shù)
example.limit((page - 1) * 200, 200);
//03.查詢
return myService.query(example);
}
- eg3
private List<Info> batchQuery(TRequest request) {
List<Info> result = new ArrayList<>();
int page = 1;
List<Info> infoList = query(request, page);
while (CollectionUtils.isNotEmpty(infoList) && page <= 1000) {//一次200,循環(huán)1000次,就是20w的數(shù)據(jù)量,肯定夠了
result.addAll(infoList);
if (200 > skuStockSaleInfos.size()) {
break;
}
page++;
infoList = query(request, page);
}
return result;
}
private List<Info> query(TRequest request, int page) {
//01.構(gòu)建查詢條件
Paging paging = new Paging();
paging.setOffset((page - 1) * 200);
paging.setLimit(200);
request.setPaging(paging);
//02.查詢
TResponse response = skuService.query(request);
if (response != null && response.getCode() == 0) {
return response.getInfoList();
} else {
return Collections.emptyList();
}
}
- eg4
List<DO> result = Lists.newArrayList();
boolean loop = true;
long id = 0L;
do {
XxxDOExample example = new XxxDOExample();
example.limit(200);
example.setOrderByClause("id asc");
XxxDOExample.Criteria criteria = example.createCriteria();
criteria1.andValidEqualTo(Boolean.TRUE);
criteria1.andIdGreaterThan(id);
List<DO> selectByExample = myMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(selectByExample)) {
result.addAll(selectByExample);
int size = selectByExample.size();
if (size < 200) {
loop = false;
} else {
id = selectByExample.get(size - 1).getId();
}
} while (loop);
第一次查詢0-100,數(shù)據(jù)。(過濾或者處理一下這100條數(shù)據(jù))后,存入list中,fetchCount = 100,
第二次查詢100-200。(過濾或者處理一下這100條數(shù)據(jù))后,存入list中,fetchCount = 200,
···
直到第10次處理完,fetchCount == total(1000)了,needFalse = false,停止查詢
補(bǔ)充:為什么采用這種,每次查詢100條,(處理或不處理)存入list,直到全部1000條都(處理或不處理)存入list。而不是直接一次查詢出這1000條數(shù)據(jù)
解:因?yàn)槿绻悴徊樵円淮?,你根本就不知道?shù)據(jù)庫中有1000條滿足條件的數(shù)據(jù)。所以,你也可以先查詢一次limit offset(0-1)查出total = 1000,此時(shí)你再執(zhí)行sql查詢page(0-1000)一次全部查出來放入list
limit 20000 , 10:從第20001行數(shù)據(jù)開始查找,查找10條(20001、20002、····200010)=》 where id 〉 20000 limit 0 ,10。PageModel即父類RowBounds(mysql中的)即這種形式limit、offset
limit 10 offset 3 :(從第4行開始查找,找10條數(shù)據(jù)),即4、5、6、···13。
<if test="rows != null">
<if test="offset != null">
limit ${offset}, ${rows} 偏移量、多少條
</if>
<if test="offset == null">
limit ${rows}
</if>
</if>
這里limit ${offset}, ${rows} 對(duì)比 limit 20000 , 10
即offset是偏移量,從第20001開始查詢,查10條。 這里是limit 0,1000 從第一條開始查查詢1000條
- eg5
return Lists.partition(skuIds, 200).stream().map(skus -> {
XxxDOExample example = new XxxDOExample();
example.createCriteria().andSkuIdIn(skus)
.andValidEqualTo(Boolean.TRUE);
return example;
}).map(example -> myMapper.selectByExample(example))
.reduce((list1, list2) -> {
list1.addAll(list2);
return list1;
}).orElse(Lists.newArrayList());
3、分頁查詢注意事項(xiàng)
只要使用分頁查詢,必須加上order by
1、原因
不使用order by,分頁查詢的數(shù)據(jù)不準(zhǔn)確
-
背景:
select查詢,如果不走二級(jí)索引查詢,查詢結(jié)果默認(rèn)是按照主鍵id,正序排序;
如果走了二級(jí)索引,則結(jié)果默認(rèn)按二級(jí)索引排序展示
-
問題復(fù)現(xiàn)
select limit 0,5,使用了二級(jí)索引A進(jìn)行查詢,則結(jié)果按照索引A正序排序,為:7,8,9,1,2;
又進(jìn)行了select 5,10查詢第二頁;
此時(shí),因?yàn)閿?shù)據(jù)庫原因(主從切換,原本該走從查詢的,現(xiàn)在走主查詢了),或數(shù)據(jù)量變化(原本數(shù)據(jù)量級(jí)該走A索引查詢的,現(xiàn)在走B索引查詢了)
select limit 5,5,使用了二級(jí)索引B進(jìn)行查詢,則結(jié)果按照索引B正序排序,為:11,12,13,14,2;導(dǎo)致id = 2的數(shù)據(jù),在第一頁 和 第二頁分頁查詢結(jié)果中都出現(xiàn)了?。?!甚至?xí)?dǎo)致數(shù)據(jù)丟失
2、解:
分頁查詢一定使用order by
3、SOP
3.1 分頁查詢?nèi)繑?shù)據(jù)(200、200、200 —)
-
無腦order by id asc即可
-
原因:
此時(shí)如果order by 字段a,會(huì)有以下問題
-
字段a,不是聯(lián)合索引一員,導(dǎo)致走不到索引
-
字段a,是聯(lián)合索引一員,但是,中間斷了x_y_z_a,但是本次查詢條件僅有x_y ,order by a,也會(huì)使索引失效
-
字段a,是聯(lián)合索引一員,且連續(xù),能走到索引,但是order by a字段,a字段有很多相同的數(shù)據(jù)。比如a字段為倉id
select order by a ,limit 0, 5 ,結(jié)果為7,8,9,1,2
-
? select order by a ,limit 5, 5 ,結(jié)果為2,11,12,13,14
? 原因就是a字段有很多相同的數(shù)據(jù),order by a,前后兩頁也有可能有相同數(shù)據(jù)
? 比如聯(lián)合索引為valid_poiId,select * from table where valid = 1 limit 0,200這個(gè)時(shí)候查出來的數(shù)據(jù)都是valid = 1的,因此查詢結(jié)果會(huì)按照聯(lián)合索引中的第二個(gè)字段poiId正序排序的?。?!
即生效sql實(shí)際上為select * from table where valid = 1 order by poiId asc limit 0,200
問題:當(dāng)poi_id有序增長時(shí),id的增長并不有序,甚至可能跨度很大?。?!,導(dǎo)致翻頁時(shí),如果使用了granThanId方式,取最后一條數(shù)據(jù)的id可能跳躍很大,導(dǎo)致漏數(shù)據(jù)。
復(fù)現(xiàn):
查詢結(jié)果 poiId id
? 1 10009577 777
? 2 10001014 77777777
這樣即使查詢出來的兩條數(shù)據(jù)按poiId排序挨在一起,但是id卻跨度很大很大。上一次granthanId的id為776,不會(huì)丟數(shù)據(jù)。這一次granThanid的id為77777777,id > 77777777,這樣777- 77777777中間很多id的數(shù)據(jù)都沒查出來!??!相當(dāng)于丟數(shù)據(jù)了
所以,此時(shí)必須添加一個(gè)能確定順序的索引,即order by a asc,id asc 。不如,直接order by id
3.2 分頁查詢?nèi)繑?shù)據(jù),建議使用greathanId文章來源:http://www.zghlxwxcb.cn/news/detail-731497.html
3.3 如果是頁面分頁查詢某一頁的數(shù)據(jù),而且需要字段a排序展示,則order by a asc,id asc文章來源地址http://www.zghlxwxcb.cn/news/detail-731497.html
- 原因:如果直接order by id,則查詢出來的幾條數(shù)據(jù),不是按a字段排序的,可能不符合要求(a字段為銷量,order by id查詢出來的幾條數(shù)據(jù),銷量可能不是最高的前幾條)
example.setOrderByClause("poi_id asc, create_at asc");
到了這里,關(guān)于批量循環(huán)查詢的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!