流式查询及MyBatis Plus游标分页

流式查询
流式查询是指查询成功后不返回整个结果集,而是返回一个迭代器,应用程序可以通过迭代器逐条获取查询结果。流式查询的优势在于能够降低内存使用。例如,当需要从数据库中获取一千万条记录,但内存不足时,就需要进行分页查询。

分页查询需要按顺序查询并设置参数来记录当前进度,并在下次查询时将进度作为参数传入。否则会出现深度分页的情况。查询效率取决于表的设计,如果设计不佳,每次查询都会是一次单独的低效查询。

而流式查询不需要自行记录进度(数据库来记录),即使表设计较差或SQL较为复杂,也仅需要一次低效查询。在流式查询过程中,需要保证数据库连接保持打开状态,否则会导致流关闭。MyBatis通过游标Cursor实现了流式查询,而MyBatis Plus基于MyBatis,自然也支持流式查询。

如何使用
编写一个获取流的Mapper,无需其他配置,就像平常的查询一样在Mapper中定义查询,并将返回结果设为Cursor即可实现流式查询。SQL也按照常规的查询条件编写,无需添加类似limit的参数。

1. 配置游标分页

在MyBatis Plus中,使用游标分页需要在mybatis-config.xml或application.yml中添加配置:

mybatis-plus:
configuration:
settings:
useCursorFetch: true

获取一个打开状态的连接
使用流式查询需要保证数据库连接保持打开状态。通常情况下,使用MyBatis执行一次查询后,连接会被关闭或重置。因此,需要一些方法来保持连接。

使用事务
事务执行完毕之前连接会一直保持,因此可以使用事务来保持连接。这是最简单的方法,但需要注意的是,由于cursor在遍历结束后会主动关闭连接,因此:

1. 方法内事务是正常的,在cursor查询前和遍历后的数据操作仍然是一个事务。从这里可以猜测,连接并不在遍历完立即关闭,而是采用了类似AOP的手段在方法末尾关闭。
2. 如果使用了数据库连接池,那么池中的连接会被关闭。这可能并不会导致连接池数量减少,因为连接池的连接数据依赖于各自的规则。当有连接断开,连接池会根据自己的策略进行相应的处理,比如重新建立。因此不需要过分关注这个,但需要注意这个行为可能带来的影响。

循环获取数据
Cursor继承了迭代器,可以通过Cursor获取其Iterator,或者直接使用for循环来获取数据。需要注意的是,Cursor在查询一瞬间数据就固化了,如果先查询,再更新,再遍历,即使在同一个事务里面,获得的结果也是未更新的数据。

关闭流
Cursor在遍历结束后会主动关闭连接。如果未遍历结束中途退出,可以调用Cursor的close方法关闭连接。推荐在finally内总是调用close或者try(resource)来保证连接总是被正常关闭。

在使用MyBatis Plus的游标分页时,有一些注意事项和建议:

数据库支持:游标分页依赖数据库的游标支持,因此确保数据库支持游标分页功能。

分页大小:需要根据实际情况设置合适的分页大小,过小可能导致频繁查询,过大可能失去游标分页的优势。

及时关闭游标:使用Cursor时,确保在处理完数据后及时关闭游标,释放资源。

性能监控:对于大数据量的场景,建议进行性能监控和测试,确保游标分页带来的性能提升符合预期。

合理使用缓存:需要根据实际情况考虑是否使用缓存,以及如何合理使用缓存,以提高查询效率。

版本更新:MyBatis Plus的版本可能会更新,建议关注最新版本的特性和改进,以获取更好的支持和性能。

标签:游戏攻略