mybatisplus分页查询,执行了多次统计查询
时间: 2025-06-08 17:20:03 浏览: 14
### MyBatisPlus分页查询多次统计查询的优化解决方案
在使用 MyBatis-Plus 进行分页查询时,可能会遇到多次执行统计查询的问题。这是因为 MyBatis-Plus 默认会在分页查询时生成两条 SQL 语句:一条用于查询总记录数(`COUNT`),另一条用于查询分页数据。如果 `COUNT` 查询过于频繁或性能低下,可以采取以下方法进行优化。
#### 1. 禁用 `COUNT` 查询优化
MyBatis-Plus 提供了一个属性 `optimizeCountSql`,用于控制是否启用优化的 `COUNT` 查询逻辑[^4]。当该属性设置为 `true` 时,MyBatis-Plus 会尝试通过子查询的方式优化 `COUNT` 查询,但这可能导致某些复杂场景下的性能问题。可以通过以下代码禁用此优化:
```java
Page page = new Page<>();
page.setCurrent(MapUtils.getIntValue(paramMap, "pageNum"));
page.setSize(MapUtils.getIntValue(paramMap, "pageSize"));
// 关闭count sql的优化
page.setOptimizeCountSql(false);
```
禁用优化后,MyBatis-Plus 将直接执行标准的 `COUNT` 查询,避免因子查询导致的性能问题。
#### 2. 手动控制 `COUNT` 查询
如果不需要每次分页查询都返回总记录数,可以通过设置 `searchCount` 属性来手动控制是否执行 `COUNT` 查询。将 `searchCount` 设置为 `false` 可以完全跳过 `COUNT` 查询:
```java
Page page = new Page<>();
page.setCurrent(MapUtils.getIntValue(paramMap, "pageNum"));
page.setSize(MapUtils.getIntValue(paramMap, "pageSize"));
// 禁用总记录数查询
page.setSearchCount(false);
```
需要注意的是,禁用 `COUNT` 查询后,分页结果中将不再包含总记录数信息,适用于仅需要当前页数据的场景。
#### 3. 使用缓存机制
对于一些固定的查询条件,可以考虑引入缓存机制来减少重复的 `COUNT` 查询。例如,可以使用 Redis 或其他内存数据库存储查询条件对应的总记录数,并在分页查询时优先从缓存中获取:
```java
String cacheKey = "total_count:" + queryCondition;
Long totalCount = redisTemplate.opsForValue().get(cacheKey);
if (totalCount == null) {
// 如果缓存中不存在,则执行 COUNT 查询并将结果存入缓存
totalCount = baseMapper.selectCount(queryWrapper);
redisTemplate.opsForValue().set(cacheKey, totalCount, Duration.ofMinutes(5));
}
```
通过缓存机制,可以显著减少对数据库的压力,特别是在高并发场景下。
#### 4. 数据库层面的优化
除了调整 MyBatis-Plus 的配置外,还可以从数据库层面优化 `COUNT` 查询的性能。例如:
- 确保查询字段上有合适的索引,尤其是排序字段和过滤条件字段。
- 对于大表查询,可以考虑使用覆盖索引或分区表技术来加速 `COUNT` 查询[^1]。
以下是创建索引的示例代码(以 MySQL 为例):
```sql
CREATE INDEX idx_created_time ON test_table(created_time);
```
#### 5. 自定义分页策略
如果默认的分页机制无法满足需求,可以考虑自定义分页策略。例如,通过偏移量(`OFFSET`)和限制(`LIMIT`)实现分页查询,同时手动计算总记录数:
```java
Integer offset = (page.getCurrent() - 1) * page.getSize();
List<Entity> data = baseMapper.selectListByOffset(offset, page.getSize());
```
这种方式可以绕过 MyBatis-Plus 的默认分页逻辑,从而更灵活地控制查询行为。
---
### 示例代码
以下是一个完整的分页查询优化示例:
```java
Page page = new Page<>();
page.setCurrent(MapUtils.getIntValue(paramMap, "pageNum"));
page.setSize(MapUtils.getIntValue(paramMap, "pageSize"));
// 禁用 COUNT 查询优化
page.setOptimizeCountSql(false);
// 禁用总记录数查询(可选)
page.setSearchCount(false);
IPage<Entity> result = entityService.page(page, queryWrapper);
return result.getRecords();
```
---
阅读全文
相关推荐
















