searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

MyBatis实现大批量数据查询优化

2024-10-28 09:27:22
15
0

       一般在业务系统需要从 MySQL 数据库里读取 100w 数据行进行处理时,这种大数据量的查询,就不能使用普通的查询方式,直接将数据全部加载出来到内存中,很可能会发生OOM(内存溢出),并且对应大数据量的查询,查询会很耗时,从而不能满足业务需求,该查询方式会耗费大量的时间和内存去把数据库查询的结果封装成需要的对象,所有这种方式是远远不能满足业务需求的,对于百万级以上的数据需要对查询方式做特殊处理,下面将介绍三种处理大批量数据查询的方式:

1、分页查询

       对于大数据量的查询,我们可以使用分页来进行查询,在使用分页前,我们可以将要查询的表上添加合适的索引,根据条件查询的时候,没有索引,便需要全表扫描,一旦数据量超过百万甚至千万,一条查询SQL执行往往需要几十秒甚至更多,在添加合适的索引后,使用分页方式来查询我们所需的数据,一般我们查询的数据并不是全部都需要的,使用分页来限制输出的数据条数,大程度缩短查询时间,一般使用LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数,参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目,但注意初始记录行的偏移量是 0(而不是 1),LIMIT # OFFSET #。在使用中需要注意:1、limit语句的查询时间与起始记录的位置成正比;2、mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用。所有我们可以根据业务需求按需进行使用。

2、流式查询

       流式查询是一种在查询成功后返回迭代器而不是整个结果集合的方式,允许逐条处理查询结果。这种方法的主要优势在于减少内存使用。当需要从数据库中提取大量数据(如100万条记录)而内存不足时,传统的分页查询可能会因为表设计不佳而效率低下。因此,流式查询成为数据库访问框架的一个重要特性。在 MyBatis 中,流式查询能够防止因数据量过大而导致的内存溢出(OOM)。但需注意的是,执行流式查询后,数据库连接会保持开启,用户需要在获取完所有数据后手动关闭该连接。此外,在数据未完全读取(或关闭)之前,不能对连接进行其他查询,否则会引发异常。

       MyBatis 提供了接口用于流式查询,使用流式查询时,需要确保对所查询表的并发访问,因为它会独占连接,因此应尽快处理结果。当查询数据达到上万条的时候相应过慢。当需要遍历处理一个非常大的查询结果时,如果不希望一次性将所有数据加载到客户端内存中,可以考虑使用流式查询。在分库分表的场景中,即使单个表的查询结果不大,如果某个查询涉及多个库和表,并且需要对结果进行合并、排序等操作,仍然可能导致内存溢出。深入研究 sharding-sphere 的代码可以发现,除了在 GROUP BYORDER BY 字段不一致的情况下,其他大多数场景都非常适合使用流式查询。这种方式能够最大限度地降低客户端内存的消耗。流式查询内存会保持稳定,不会随着记录的增长而增长。其内存大小取决于批处理大小BATCH_SIZE的设置,该尺寸越大,内存会越大,所以BATCH_SIZE应该根据业务情况设置合适的大小。

3、游标查询

      在处理大量数据时,为了避免内存泄漏,可以考虑使用游标方式进行数据查询。这种方法通常比传统查询更高效。当需要查询百万级的数据时,游标方式不仅能节省内存消耗,还能避免一次性加载所有数据。通过这种方式,可以逐条处理数据或按批次取出部分数据。可以在一次查询中指定 fetchSize,然后逐步处理所有数据,直到处理完成。

总结

     流式查询、游标查询可以避免 OOM,数据量大可以考虑此方案。但是这两种方式会占用数据库连接,使用中不会释放,所以线上针对大数据量业务用到游标和流式操作,一定要进行并发控制 另外针对 JDBC 原生流式查询,Mybatis 中也进行了封装,虽然会慢一些,但是功能以及代码的整洁程度会好上不少。在实际应用中,我们可以根据业务数据量情况,选择合适的方式进行查询,来高效的获取目标数据。

0条评论
0 / 1000
刘****航
2文章数
0粉丝数
刘****航
2 文章 | 0 粉丝
刘****航
2文章数
0粉丝数
刘****航
2 文章 | 0 粉丝
原创

MyBatis实现大批量数据查询优化

2024-10-28 09:27:22
15
0

       一般在业务系统需要从 MySQL 数据库里读取 100w 数据行进行处理时,这种大数据量的查询,就不能使用普通的查询方式,直接将数据全部加载出来到内存中,很可能会发生OOM(内存溢出),并且对应大数据量的查询,查询会很耗时,从而不能满足业务需求,该查询方式会耗费大量的时间和内存去把数据库查询的结果封装成需要的对象,所有这种方式是远远不能满足业务需求的,对于百万级以上的数据需要对查询方式做特殊处理,下面将介绍三种处理大批量数据查询的方式:

1、分页查询

       对于大数据量的查询,我们可以使用分页来进行查询,在使用分页前,我们可以将要查询的表上添加合适的索引,根据条件查询的时候,没有索引,便需要全表扫描,一旦数据量超过百万甚至千万,一条查询SQL执行往往需要几十秒甚至更多,在添加合适的索引后,使用分页方式来查询我们所需的数据,一般我们查询的数据并不是全部都需要的,使用分页来限制输出的数据条数,大程度缩短查询时间,一般使用LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数,参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目,但注意初始记录行的偏移量是 0(而不是 1),LIMIT # OFFSET #。在使用中需要注意:1、limit语句的查询时间与起始记录的位置成正比;2、mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用。所有我们可以根据业务需求按需进行使用。

2、流式查询

       流式查询是一种在查询成功后返回迭代器而不是整个结果集合的方式,允许逐条处理查询结果。这种方法的主要优势在于减少内存使用。当需要从数据库中提取大量数据(如100万条记录)而内存不足时,传统的分页查询可能会因为表设计不佳而效率低下。因此,流式查询成为数据库访问框架的一个重要特性。在 MyBatis 中,流式查询能够防止因数据量过大而导致的内存溢出(OOM)。但需注意的是,执行流式查询后,数据库连接会保持开启,用户需要在获取完所有数据后手动关闭该连接。此外,在数据未完全读取(或关闭)之前,不能对连接进行其他查询,否则会引发异常。

       MyBatis 提供了接口用于流式查询,使用流式查询时,需要确保对所查询表的并发访问,因为它会独占连接,因此应尽快处理结果。当查询数据达到上万条的时候相应过慢。当需要遍历处理一个非常大的查询结果时,如果不希望一次性将所有数据加载到客户端内存中,可以考虑使用流式查询。在分库分表的场景中,即使单个表的查询结果不大,如果某个查询涉及多个库和表,并且需要对结果进行合并、排序等操作,仍然可能导致内存溢出。深入研究 sharding-sphere 的代码可以发现,除了在 GROUP BYORDER BY 字段不一致的情况下,其他大多数场景都非常适合使用流式查询。这种方式能够最大限度地降低客户端内存的消耗。流式查询内存会保持稳定,不会随着记录的增长而增长。其内存大小取决于批处理大小BATCH_SIZE的设置,该尺寸越大,内存会越大,所以BATCH_SIZE应该根据业务情况设置合适的大小。

3、游标查询

      在处理大量数据时,为了避免内存泄漏,可以考虑使用游标方式进行数据查询。这种方法通常比传统查询更高效。当需要查询百万级的数据时,游标方式不仅能节省内存消耗,还能避免一次性加载所有数据。通过这种方式,可以逐条处理数据或按批次取出部分数据。可以在一次查询中指定 fetchSize,然后逐步处理所有数据,直到处理完成。

总结

     流式查询、游标查询可以避免 OOM,数据量大可以考虑此方案。但是这两种方式会占用数据库连接,使用中不会释放,所以线上针对大数据量业务用到游标和流式操作,一定要进行并发控制 另外针对 JDBC 原生流式查询,Mybatis 中也进行了封装,虽然会慢一些,但是功能以及代码的整洁程度会好上不少。在实际应用中,我们可以根据业务数据量情况,选择合适的方式进行查询,来高效的获取目标数据。

文章来自个人专栏
大数据量业务优化
1 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0