1.通过where 条件后,量不大可以 limit index,size.
2. 量大,索引+orderby法 本质上 要有个unique_key.
order by 的key, 必须要有索引,性能好.
where unique_key > #{index} order by unique_key
nextIndex = index + 最后一个+1; (这个对多字段 unique_key是难点 )
2.1 unique_key 一个字段,基本上是id然后必要的时候,你需要对应的索引用于where筛选.
2.2 unique_key 多个字段.(难点)
2.2.1 筛选度高的放前面. (一般选id)
2.2.2 id放前面,并且把筛选条件放到同一个索引了. ( 筛选低的放前面 ? 待试验. 可以先= ,最好一个 > .)
A场景: 如果是查询条件是> ,相当于会有两个字段都是> 或者 < . 是否能有效利用到 联合索引? 最好另外一个改成 in( ) .
nextIndex = 最后一个的 多个元素, 然后统一 字段1 > indexA and 字段2 > indexB .
核心抓住: 回传所有的keyCursor.(整体有序不代表, 不等各个字段分拆后 字段1 > indexA and 字段2 > indexB 有序
而是 if( fist > indexA,1, if (fist < indexA,-1,if(second > indexB ,1,if(second= indexB ,1))) = 1 ,代表大于这个unique.
unique_key: id
比如 idx_id_start_time.
这样你就可以写分页的sql了.
2.2 unique_key 多个字段.
2.2.1 查询条件里有这几个字段
2.2.2 查询条件里没这几个字段.
示例:
含筛选条件的多分组分页小数据量查询.
两个size, fetchSizeForClient : 用户期望获取的size.sizeForDb 向 db中查询的次数.
场景1: 如果前端设置fetchSizeForClient=1,sizeForDb=50 可能会导致多查49条数据.
场景2: 如果filter条件很多, sizeForDb太小就会导致db查询多次, 导致性能比较差. sizeForDb不能太大,也不能太小.
/**
* sql示例: select * from table order by name,id limit #{},#{}
*
* @param searchBatchFunction search回调接口,可以硬写死
* @param fetchSizeForClient
* @param pageItemFilter filter回调接口,可以硬写死
* @param <T>
* @return
* @throws ServiceException
*/
private <T> PageVO<List<T>> fetchRoomPageListsFromDBWithFilter(SearchBatchFunction searchBatchFunction, Integer fetchSizeForClient,PageItemFilter pageItemFilter) throws ServiceException {
PageVO<List<MeetingRoomVo>> pageVo = new PageVO<>();
// 兜底初始化.
pageVo.setHasMore(false);
pageVo.setResult(Lists.<MeetingRoomVo>newArrayList());
List<MeetingRoomVo> result = Lists.newArrayList();
Long index = indexInput;
// 未获取满,继续. 内有break
while (result.size() < fetchSizeForClient) {
// 如果是获取所有,那就所有会议室挨个获取.
Integer sizeForDb = diamond.getIntDefault("PageSizeForDB", 50);
List<T> items = searchBatchFunction.execute(index, sizeForDb);
if (CollectionUtils.isEmpty(items)) {
break;
}
List<T> initialItems = Lists.newArrayList(items);
// items传入后可能会被删除元素.
T indexItem = pageItemFilter.filter( result, items);
if (indexItem == null) {
logger.debug("calacIndex_indexItemMayBeNull_null ,index={},add={}", index, initialItems.size());
index = index + initialItems.size();
} else {
// index就是序号,原因: 当前模式是 limit #{index},#{size},
Integer count = 0;
for (T item : initialItems) {
count++;
if (indexItem.getId().equals(item.getId())) {
break;
}
}
logger.debug("calacIndex_indexItemVOMayBeNull_notNull ,index={},add={},{}", index, count, JSON.toJSONString(indexItem));
index = index + count;
}
}
pageVo.setNextCursor(index);
pageVo.setResult(result);
if (fetchSizeForClient <= result.size()) {
pageVo.setHasMore(true);
} else {
pageVo.setHasMore(false);
}
return pageVo;
}
含筛选条件的多分组分页大数据量查询. (只需要将上面的加个where 条件,并且index改用)
附录:MySQL大数据量分页查询方法及其优化