coldsmog开发笔记
JS 事件笔记
Ckeditor 上传WPS图片失败问题
Springboot
SpringBoot 统一异常处理
Springboot 引入外部jar包
Springboot 打成war包
Springboot 多环境配置
SpringBoot @Scope注解学习
Springboot 快速生成项目API文档
SpringCache 缓存
Spring jetcache 二级缓存
Springboot 按条件装配类
FastJson的JsonPath语法
正则表达式语法
Spring 路径匹配
Feign 基础数据操作
监控Feign调用metrics
Springboot feign的性能优化
Jackson 设置序列化属性
SpringBoot 集成 Spring Data Mongodb 操作 MongoDB
MongoDB 的一些注意事项
MongoDB 指令对比
Jackson 解析XML
Springboot Redis注册
SpringBoot RedisTemplate批量插入
Springboot 指标监控Micrometer
springboot validation 注解校验
springboot 引入配置
Springboot 静态文件处理
Springboot 导出csv文件
Springboot 事件驱动(发布/订阅模式)
Springboot 启动过程和扩展点
Springboot 优化停机上下线
Spring自动装配 - 干饭角度学习
Springboot ShardingJDBC
Springboot的重试
springboot 动态修改端口
Oracle
Oracle 中实现自增ID
Oracle 定时任务
Oracle 解锁临时表
Oracle 检查连接数
Oracle 表空间
Oracle 解释执行SQL
markdown作图(适用typora)
服务器压测
业务对象层和数据层
并发限流处理
中间件
Yarn的使用
Dubbo学习笔记-RPC扩展和本地Mock
Dubbo学习笔记-泛化实现进行mock
Redis缓存穿透,缓存击穿,缓存雪崩
Galera 集群说明
Pip 镜像
pip 使用
MySQL命令行
数据库缓存双写方案
Git相关操作
Redis 操作时间复杂度一览
nacos 杂记
mybatis 散记
shardingjdbc
一次线上事故排查发现的Caffeine缓存死锁问题
设计模式
重新讲讲单例模式和几种实现
更优雅地实现策略模式
Http-headers
Prometheus 杂散笔记
JAVA 散记
CompletableFuture
Gson、FastJson、Jackson、json-lib对比总结
jackson 时间的序列化踩坑
JVM
自定义注解
mysql类型和java类型 转换一览表
枚举维护一个Map<value, Enum>的映射
Java中String +、concat、StringBuilder、StringBuffer 性能对比
TraceId 使用
MySQL 多数据源处理
Mybatis-plus 流式查询
JAVA发送win 桌面通知
idea 启动项目失败非代码问题杂记
Lambda 简述
Arthas 使用笔记
一种链式更新数据的数据模式
Skywalking 新增中间件插件
Redission 使用
数据导出为图片
IDEA 的热重启
Netty 工具类
maven 插件
TCP 抓包
本文档使用 MrDoc 发布
-
+
首页
Mybatis-plus 流式查询
## 1. 简述 传统查询是一次性取出所有数据然后处理,对上百万的数据突出两个问题:1. 处理时间长,阻塞数据库IO; 2. 一次性占用内存多,易OOM; 流式查询则使用数据库游标,查一行处理一行,消耗内存较少,不阻塞数据库IO,在大数据处理场景中推荐使用。 ## 2. DAO层的流式处理函数的声明 ```java /** * (Order)表数据库访问层 * * @author liudong * @since 2020-09-15 17:07:13 */ @Mapper public interface OrderDao extends BaseMapper<OrderDO> { /** * ResultType对象=ResultHandler需要处理的对象=SQL查询结果 * 其余参数和正常一样,用@Param标记并传递 */ @Select("select * from Order where code=#{obj.code}") @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE) @ResultType(OrderDO.class) void streamDoHandler(@Param("obj") OrderDO order, ResultHandler<OrderDO> handler); } ``` ## 3. 流式处理的使用 ```java public class OrderService { @Resource private OrderDao orderDao; public synchronized void doHandle(Consumer<OrderDO> consumer) { OrderDO order = new OrderDO(); order.setCode("test"); orderDao.streamDoHandler(order, resultContext -> { OrderDO order = resultContext.getResultObject(); // 处理函数,我此处用lambda从而让可以将处理函数单独拆出来 consumer.accept(order); // 当然,你也可以直接在此处理 System.out.println(order); }); } } ``` ## 4. 一些踩坑 **Oracle的fetchSize建议设置成1000,MySQL的fetchSize建议设置成Integer.MIN_VALUE** sharding-sphere的执行引擎对数据库的连接方式提供了两种:内存限制模式和连接限制模式。参考:[sharding-sphere](https://shardingsphere.apache.org/document/current/cn/features/sharding/principle/execute),在内存限制模式中(也就是要使用流式查询的场景),对于每一张表的查询,都需要创建一个数据库连接,如果跨库跨表查询操作很多,这对数据库连接数的消耗将会非常大。这是为什么要这么限制呢? 原来mysql本身并没有FetchSize方法, 它是通过使用CS阻塞方式的网络流控制实现。服务端不会一下发送大量数据到客户端撑爆客户端内存,这种实现方式比起商业数据库Oracle使用客户端、服务器端缓冲块暂存查询结果数据来说,简直是弱爆了!这样带来的问题:如果使用了流式查询,**一个MySQL数据库连接同一时间只能为一个ResultSet对象服务,并且如果该ResultSet对象没有关闭,势必会影响其他查询对数据库连接的使用!**此为大坑,难怪sharding-sphere费劲心思要提供两种数据库连接模式,如果应用对数据库连接的消耗要求严苛,那么流式查询就不再适合。 那么有什么解决办法呢? 根据官方文档的建议,给结果集设置 forward-only, read-only 以及将 fetch size 设置为 Integer.MIN_VALUE, 即表明让 MySQL 以流式传输结果集中的数据. 在此之后, 将逐行检索使用该语句创建的任何结果集. 这种方法有一些注意事项. 您必须先读取结果集中的所有行 (或将其关闭), 然后才能对连接发出任何其他查询, 否则将引发异常.如果使用流式结果, 如果您想保持对生成结果集的语句所引用的表的并发访问, 请尽快处理它们. 另一种选择是每次使用基于游标的流来检索一组行. 这可以通过将连接属性 useCursorFetch 设置为 true, 然后调用 setFetchSize(int) 来设置每次要获取的行数: ``` conn = DriverManager.getConnection("jdbc:mysql://localhost/?useCursorFetch=true", "user", "s3cr3t"); stmt = conn.createStatement(); stmt.setFetchSize(100); rs = stmt.executeQuery("SELECT * FROM your_table_here"); ``` 参考资料: [深入了解MySQL的流式查询机制](https://blog.csdn.net/nym232/article/details/89240054) [MySQL 流式查询的用法和坑](https://segmentfault.com/a/1190000042050623) [connector-j-reference-implementation-notes](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-implementation-notes.html)
寒烟濡雨
2023年5月9日 21:56
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码