MySQL中流式查询方法
发布时间:2023-12-23 19:19:56 所属栏目:MySql教程 来源:DaWei
导读: 这篇文章主要讲解了“MySQL中流式查询方式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL中流式查询及游标
这篇文章主要讲解了“MySQL中流式查询方式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL中流式查询及游标查询的方式是什么”吧! 一、业务场景 现在业务系统需要从 MySQL 数据库里读取 500w 数据行进行处理 迁移数据 导出数据 批量处理数据 二、罗列一下三种处理方式 常规查询:一次性读取 500w 数据到 JVM 内存中,或者分页读取 流式查询:每次读取一条加载到 JVM 内存进行业务处理 游标查询:和流式一样,通过 fetchSize 参数,控制一次读取多少条数据 2.1 常规查询 默认情况下,完整的检索结果集会将其存储在内存中。在大多数情况下,这是最有效的操作方式,更易于实现。 假设单表 500w 数据量,没有人会一次性加载到内存中,一般会采用分页的方式。 在这里,测试demo中只是为了监控JVM,所以没有采用分页,一次性将数据载入内存中 @Test public void generalQuery() throws Exception { // 1核2G:查询一百条记录:47ms // 1核2G:查询一千条记录:2050 ms // 1核2G:查询一万条记录:26589 ms // 1核2G:查询五万条记录:135966 ms String sql = "select * from wh_b_inventory limit 10000"; ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(sql); int count = 0; while (rs.next()) { count++; } System.out.println(count); } JVM监控 我们将对内存调小-Xms70m -Xmx70m 整个查询过程中,堆内存占用逐步增长,并且最终导致OOM: java.lang.OutOfMemoryError: GC overhead limit exceeded 1、频繁触发GC 2、存在OOM隐患 MySQL中流式查询及游标查询的方式是什么 2.2 流式查询 流式查询有一点需要注意:必须先读取(或关闭)结果集中的所有行,然后才能对连接发出任何其他查询,否则将引发异常,其 查询会独占连接。 从测试结果来看,流式查询并没有提升查询的速度 @Test public void streamQuery() throws Exception { // 1核2G:查询一百条记录:138ms // 1核2G:查询一千条记录:2304 ms // 1核2G:查询一万条记录:26536 ms // 1核2G:查询五万条记录:135931 ms String sql = "select * from wh_b_inventory limit 50000"; statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); statement.setFetchSize(Integer.MIN_VALUE); ResultSet rs = statement.executeQuery(sql); int count = 0; while (rs.next()) { count++; } System.out.println(count); } JVM监控 我们将堆内存调小-Xms70m -Xmx70m 我们发现即使堆内存只有70m,却依然没有发生OOM MySQL中流式查询及游标查询的方式是什么 2.3 游标查询 注意: 1、需要在数据库连接信息里拼接参数 useCursorFetch=true 2、其次设置 Statement 每次读取数据数量,比如一次读取 1000 从测试结果来看,游标查询在一定程度缩短了查询速度 @Test public void cursorQuery() throws Exception { Class.forName("com.mysql.jdbc.Driver"); // 注意这里需要拼接参数,否则就是普通查询 conn = DriverManager.getConnection("jdbc:mysql://101.34.50.82:3306/mysql-demo?useCursorFetch=true", "root", "123456"); start = System.currentTimeMillis(); // 1核2G:查询一百条记录:52 ms // 1核2G:查询一千条记录:1095 ms // 1核2G:查询一万条记录:17432 ms // 1核2G:查询五万条记录:90244 ms String sql = "select * from wh_b_inventory limit 50000"; ((JDBC4Connection) conn).setUseCursorFetch(true); statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); statement.setFetchSize(1000); ResultSet rs = statement.executeQuery(sql); int count = 0; while (rs.next()) { count++; } System.out.println(count); } JVM监控 我们将堆内存调小-Xms70m -Xmx70m 我们发现在单线程情况下,游标查询和流式查询一样,都能很好的规避OOM,并且游标查询能够优化查询速度。 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐