记录一下单表的mysql百万数据用java代码优化分页--逻辑分页

本文介绍了在MySQL中使用子查询进行分页优化的方法,通过创建总数表以提升查询效率,并展示了在MyBatis和MyBatis-Plus中的实现方式。测试结果显示,即使在处理大量数据时,分页查询也能在一秒内完成,达到了理想的性能。
摘要由CSDN通过智能技术生成

参考资料:Mysql分页以及优化的几种方式。_技术砖家--Felix的博客-CSDN博客_mysql 分页优化

(本文采用的是参考文章中分页优化的第三种,子查询方式,第四种试了一下,十多秒页面才出数据)

准备两个表(存数据的表 和 存对应的表的总数)

测试表(存放数据):

 总数表(存放count数据 。当然,对应的表每做一次添加删除也需要修改这个表的数据。如果数据在一百万以内不需要使用,性能还是可以的):

 

mybatis实现:

mapper接口:

/**
     * 分页
     * @param currentPage 当前页
     * @param pageSize 分页大小
     * @return 结果集
     */
    List<EmployeeExporter> getAll(@Param("currentPage") Integer currentPage,
                                  @Param("pageSize") Integer pageSize);

 xml:

<select id="getAll" resultType="EmployeeExporter">
        SELECT id, user_name, gender, age, birthday, national_area, city
        FROM `employee`
        WHERE id >=
              (SELECT id FROM `employee` where deleted = 0 ORDER BY id
            LIMIT #{currentPage}
            , 1)
          and deleted = 0
            LIMIT #{pageSize}
</select>

controller(测试代码直接省略service):

    @GetMapping("all")
    @ApiOperation("查找")
    public ResultVo<Object> findAll(Integer currentPage, Integer pageSize) {
        // 重新计算当前页规则  
        currentPage =((currentPage -1) * pageSize);
        //这里就是调用接口 拿到当前页的结果集
        List<EmployeeExporter> records = mapper.getAll(currentPage, pageSize);
        //这里是把总数放在一个计数表,毕竟数据量大了的话 select count(*) 执行很慢。所以就是直接返回结果
        LambdaQueryWrapper<CountPojo> wrapper = Wrappers.lambdaQuery(CountPojo.class)
                .eq(CountPojo::getName, "employee");
        //自定义一个count对象。用来存储对应的表的count总数据数
        CountPojo count = countMapper.selectOne(wrapper);
        //Integer total = mapper.getIdCount();
        log.info("records : {}", records);
        //以下是将结果集存放到map中。然后丢到result对象返回给前端
        HashMap<String, Object> map = getMap(2);
        map.put("data", records);
        map.put("total", count.getCount());
        return ResultVo.success(map);
    }

mybatis-plus实现:

    @GetMapping("all")
    @ApiOperation("查找")
    public ResultVo<Object> findAll(Integer currentPage, Integer pageSize) {
// 注:last条件中limit后面需要加空格(limit0,1)和 (limit 0,1)看懂了吗
        currentPage =((currentPage -1) * pageSize);
//子查询条件
        LambdaQueryWrapper<EmployeeExporter> sonSelect = Wrappers.lambdaQuery(EmployeeExporter.class).select(EmployeeExporter::getId)
                .orderByAsc(EmployeeExporter::getId).last("limit " + currentPage + ",1");
//拿到子查询对象的id
        EmployeeExporter one = excelService.getOne(sonSelect);
        LambdaQueryWrapper<EmployeeExporter> select = Wrappers.lambdaQuery(EmployeeExporter.class)
                .ge(EmployeeExporter::getId, one.getId())
                .last("limit " + pageSize);
//结果集
        List<EmployeeExporter> records = excelService.list(select);
        LambdaQueryWrapper<CountPojo> count = Wrappers.lambdaQuery(CountPojo.class)
                .eq(CountPojo::getName, "employee");
        CountPojo total = countMapper.selectOne(count);
        HashMap<String, Object> map = getMap(2);
        map.put("data", records);
        map.put("total", total.getCount());
        return ResultVo.success(map);
        return plusResultPlus(currentPage, pageSize);
    }

测试:

element ui + springboot

第一页:

随机一页:

 

 最后一页:

 


可以看到执行时间还是挺理想的。最后一页三百万也就一秒左右,也不知道属不属于慢sql了。

当然,可能有很多细节没考虑到,但总之还是实践了一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
假设我们有两个实体类`User`和`Order`,它们之间是一对多的关系,即一个用户可以有多个订单。我们需要实现一个连表分页查询的功能,可以按照用户的某个字段进行排序。 1. 首先在`pom.xml`文件中添加Mybatis-Plus和MySql的依赖: ```xml <!-- Mybatis-Plus依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <!-- MySql驱动依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> ``` 2. 创建两个实体类`User`和`Order`,并在`User`类中添加`@TableId`注解: ```java @Data public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; } @Data public class Order { private Long id; private Long userId; private String orderNo; private BigDecimal amount; } ``` 3. 创建`UserMapper`和`OrderMapper`接口,并继承`BaseMapper`接口: ```java public interface UserMapper extends BaseMapper<User> { } public interface OrderMapper extends BaseMapper<Order> { } ``` 4. 创建`UserAndOrderVO`类,用于封装查询结果: ```java @Data public class UserAndOrderVO { private Long userId; private String userName; private Integer userAge; private String userEmail; private Long orderId; private String orderNo; private BigDecimal orderAmount; } ``` 5. 创建`UserAndOrderMapper`接口,用于实现连表分页查询: ```java public interface UserAndOrderMapper extends BaseMapper<UserAndOrderVO> { List<UserAndOrderVO> selectUserAndOrderPage(IPage<UserAndOrderVO> page, @Param("orderByField") String orderByField, @Param("userId") Long userId); } ``` 6. 在`UserAndOrderMapper.xml`中实现具体的查询逻辑: ```xml <select id="selectUserAndOrderPage" resultMap="UserAndOrderVO"> SELECT u.id AS userId, u.name AS userName, u.age AS userAge, u.email AS userEmail, o.id AS orderId, o.order_no AS orderNo, o.amount AS orderAmount FROM user u INNER JOIN `order` o ON u.id = o.user_id <if test="userId != null"> WHERE u.id = #{userId} </if> ORDER BY ${orderByField} DESC </select> ``` 7. 在业务逻辑中调用`UserAndOrderMapper`接口中的方法,实现分页查询: ```java @Service public class UserAndOrderService { @Autowired private UserAndOrderMapper userAndOrderMapper; public IPage<UserAndOrderVO> selectUserAndOrderPage(Page<UserAndOrderVO> page, String orderByField, Long userId) { return userAndOrderMapper.selectUserAndOrderPage(page, orderByField, userId); } } ``` 以上就是使用Mybatis-Plus实现连表分页查询的全部代码。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值