java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis Plus大数据量查询慢

MyBatis Plus大数据量查询慢原因分析及解决

作者:night_gu

大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次处理及配置调优

大数据量查询慢的常见原因

MyBatis Plus 在处理大数据量查询时,性能瓶颈通常出现在数据库连接、网络传输、内存消耗和结果集处理等方面。

常见问题包括全表扫描、未合理使用分页、ORM 映射开销过大等。

优化方案

合理使用分页查询

MyBatis Plus 内置分页插件(PaginationInnerInterceptor),避免一次性加载全部数据。

配置示例:

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

查询时通过 Page 对象分页:

Page<User> page = new Page<>(1, 100); // 当前页, 每页条数
userMapper.selectPage(page, null);

启用流式查询

通过 @Options 注解启用 JDBC 流式读取,减少内存占用:

@Select("SELECT * FROM large_table")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
@ResultType(User.class)
void selectLargeData(ResultHandler<User> handler);

使用游标处理结果

结合 MyBatis 的 Cursor 逐行处理数据:

try (Cursor<User> cursor = userMapper.selectCursor(null)) {
    cursor.forEach(user -> {
        // 单行处理逻辑
    });
}

SQL 语句优化

添加必要的索引,避免 SELECT *,只查询必要字段。通过 @SqlParser 注解过滤逻辑删除等干扰:

@SqlParser(filter = true)
@Select("SELECT id, name FROM user WHERE status = 1")
List<User> selectActiveUsers();

批处理操作

插入/更新时使用 saveBatch 方法,通过 rewriteBatchedStatements=true 参数提升批量性能:

List<User> userList = ... // 大数据集合
userService.saveBatch(userList, 1000); // 每批1000条

高级方案

多数据源与读写分离

通过 @DS 注解将查询路由到从库,减轻主库压力:

@DS("slave")
@Select("SELECT * FROM read_heavy_table")
List<Record> selectReadHeavyData();

结果集二次处理

在内存充足的情况下,先通过 LIMIT 分页查询 ID,再通过 IN 查询完整数据:

-- 第一步:查询ID范围
SELECT id FROM large_table LIMIT 1000000, 1000;
-- 第二步:精确获取数据
SELECT * FROM large_table WHERE id IN (1,2,3...);

配置调优

application.yml 中调整连接池参数:

spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

监控与诊断

启用 p6spy 监控实际执行的 SQL,分析慢查询日志:

<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>

配置 spy.properties 记录执行时间:

appender=com.p6spy.engine.spy.appender.Slf4JLogger
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
customLogMessageFormat=%(executionTime) ms | %(category) | %(sql)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文