业务背景
mongodb大数据量分页查询主要耗时是查询总条数,所以有两种优化方式
1.不查询总条数,查询最近N页数据[改动略多,执行耗时很短]
2.增加页面时间范围必填条件[改动很小,执行耗时略长,与数据量有关]
[比如默认查询创建时间最近一个月的数据 根据数据量做调整,创建时间有组合索引]
这两种优化方式,都需要与产品沟通
下面着重介绍一下第一种优化方式
不查询总条数,查询最近N页数据。
类似百度,第1-6页查询10页数据,第7页开始查询查询(pageNum+4)页数据,类似懒加载
需要展示总条数,使用定时任务每天/每小时单独查询总条数放入更新到缓存中。
直接上代码
使用mongodb依赖
<!-- mongo -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
yml文件配置
spring:
data:
mongodb:
uri: mongodb://账号:密码@ip地址:端口/数据库名称?authSource=admin
业务伪代码
@Autowired
private MongoTemplate mongoTemplate;
@Override
public Page<Entity> queryPage(queryVO vo) {
Integer pageNum = vo.getPageNum();
Integer pageSize = vo.getPageSize();
Query query = new Query();
//条件拼接
query.addCriteria(Criteria.where("companyId").is(vo.getCompanyId()));
// 分页查询 查询 pageNum-1 页的数据
Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
// 排序字段
Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
query.with(sort).with(pageable);
List<Entity> list = this.mongoTemplate.find(query, Entity.class);
// 不查询总条数
// long count = mongoTemplate.count(query, Entity.class);
// 分页查询 不查询总条数 需要单独查询 是否有数据
// 第1-6页 总页数=10 从第7页开始 需要往后 + 4 页
int limitParam = (pageNum < 7 ? 10 : (pageNum + 4) ) * pageSize;
query.skip(limitParam).limit(1);
Long count = null;
long isExists = this.mongoTemplate.count(query, Entity.class);
// 如果查询结果为空 则查询总条数,如果不为空则 limitParam为总条数
if (isExists == 0) {
// 查询总条数方法 修改
query.skip(0).limit(limitParam);
count = mongoTemplate.count(query, Entity.class);
}else {
count = (long) limitParam;
}
Page<Entity> page = new Page<>();
page.setCurrent(pageNum);
page.setSize(pageSize);
page.setTotal(count);
page.setRecords(list);
return page;
}
查询效果展示
最后
elasticsearch查询速度很快,如果数据量很大比如上亿,为了加快查询速度,可以采用查询符合条件的前1万条用作总条数,用来分页
关系型数据库(mysql,PostgreSql等)都可以使用上面的两种方式优化大数量分页查询
欢迎大家评论,相互沟通学习
标签:count,pageNum,分页,mongodb,查询,条数,数据量,query,page From: https://blog.51cto.com/u_12383390/9629089