mysql三种读取模式(普通、流式、游标)

在与MySQL数据库交互时,数据的读取方式有多种选择,包括流式读取、游标读取和普通读取。每种方式都有其独特的原理、优势和劣势。本文将对这三种读取方式进行详细介绍,

1. 普通读取

介绍

普通读取是指通过JDBC的StatementPreparedStatement执行SQL查询,JDBC驱动会阻塞的一次性读取全部查询的数据到 JVM 内存中。这种方式适用于小型数据集的读取。

原理

在普通读取中,当执行查询时,JDBC会将整个结果集从数据库加载到内存中。开发者可以通过ResultSet对象逐行访问数据。

示例代码

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;

try {
    String url = "jdbc:mysql://localhost:3307/test?useSSL=false";
    connection = DriverManager.getConnection(url, user, password);
    statement = connection.createStatement();
    resultSet = statement.executeQuery("SELECT * FROM table_name");

    while (resultSet.next()) {
        System.out.println(resultSet.getString("column_name"));
    }
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    // close
    if (resultSet != null) resultSet.close();
    if (statement != null) statement.close();
    if (connection != null) connection.close();
}

优势

  • 简单易用:代码结构简单,易于理解和使用。
  • 适合小数据集:对于小型数据集,性能良好,读取速度快。

劣势

  • 内存消耗:对于大型数据集,可能导致内存消耗过大,甚至引发OutOfMemoryError
  • 不适合实时处理:无法实时处理数据,需等待整个结果集加载完成。

e4e98c4e1290477f76a085e5c8a5203b

2. 游标读取

介绍

游标读取是指通过JDBC的StatementPreparedStatement使用游标逐行读取数据。游标允许在结果集中移动,适合处理较大的数据集。

原理

游标读取通过在数据库中维护一个指向结果集的指针,允许逐行访问数据。每次读取一行数据,游标向前移动,直到结果集结束。

示例代码

  • 在连接参数中需要拼接useCursorFetch=true;
  • 创建Statement时需要设置ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY
  • 设置fetchSize控制每一次获取多少条数据
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try {
    String url ="jdbc:mysql://localhost:3307/test?useSSL=false&useCursorFetch=true";
    connection = DriverManager.getConnection(url, user, password);
    preparedStatement = connection.prepareStatement("SELECT * FROM table_name", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    preparedStatement.setFetchSize(100); //set fetchSize
    resultSet = preparedStatement.executeQuery();

    while (resultSet.next()) {
        System.out.println(resultSet.getString("column_name"));
    }
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    // close reources
    if (resultSet != null) resultSet.close();
    if (preparedStatement != null) preparedStatement.close();
    if (connection != null) connection.close();
}

优势

  • 内存效率:只在内存中保留当前行,适合处理大型数据集。
  • 逐行处理:可以逐行读取和处理数据,适合实时数据处理场景。

劣势

  • 复杂性:相较于普通读取,代码结构稍复杂。
  • 性能开销:在某些情况下,逐行读取可能会导致性能下降。

游标查询需要注意的点:

由于MySQL方不知道客户端什么时候将数据消费完,而自身的对应表可能会有DML写入操作,此时MySQL需要建立一个临时空间来存放需要拿走的数据。因此对于当你启用useCursorFetch读取大表的时候会看到MySQL上的几个现象:

  • IOPS飙升 (IOPS (Input/Output Per Second):磁盘每秒的读写次数)
  • 磁盘空间飙升
  • 客户端JDBC发起SQL后,长时间等待SQL响应数据,这段时间就是服务端在准备数据
  • 在数据准备完成后,开始传输数据的阶段,网络响应开始飙升,IOPS由“读写”转变为“读取”。
  • CPU和内存会有一定比例的上升

3. 流式读取

介绍

流式读取是指通过JDBC的StatementPreparedStatement以流的方式读取数据,适合处理非常大的数据集。

原理

流式读取通过设置ResultSet的类型和并发模式,允许在不将整个结果集加载到内存的情况下,逐行读取数据。通常结合setFetchSize()方法来控制每次从数据库中获取的行数。

示例代码

Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try {
    String url = "jdbc:mysql://localhost:3307/test?useSSL=false";
    connection = DriverManager.getConnection(url, user, password);
    preparedStatement = connection.prepareStatement("SELECT * FROM table_name", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    preparedStatement.setFetchSize(1000); // 设置每次读取的行数
    //OR USEING com.mysql.jdbc.StatementImpl
    //((StatementImpl) statement).enableStreamingResults();
    resultSet = preparedStatement.executeQuery();

    while (resultSet.next()) {
        System.out.println(resultSet.getString("column_name"));
    }
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    // 关闭资源
    if (resultSet != null) resultSet.close();
    if (preparedStatement != null) preparedStatement.close();
    if (connection != null) connection.close();
}

优势

  • 极高的内存效率:适合处理超大数据集,内存占用极低。
  • 实时处理能力:可以实时处理数据,适合流式数据分析。

劣势

  • 复杂性:实现相对复杂,需要合理设置fetch size
  • 性能问题:在某些情况下,频繁的数据库访问可能导致性能下降。

流式查询应该注意的坑

WARN ] 2024-12-26 09:36:50.365 [] job-file-log-676bc326966a463e08520799 - [srtosr][sr35] - Query 'his_config_info_exp' snapshot row size failed: java.lang.RuntimeException: io.tapdata.flow.engine.V2.exception.node.NodeException: Query table 'his_config_info_exp' count failed: No operations allowed after connection closed.
java.util.concurrent.CompletionException: java.lang.RuntimeException: io.tapdata.flow.engine.V2.exception.node.NodeException: Query table 'his_config_info_exp' count failed: No operations allowed after connection closed.
 at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
 at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
 at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1643)
 at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1632)
 at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
 at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
 at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
 at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
MySQL Connector/J 5.1 Developer Guide中原文:

There are some caveats with this approach. You must read all of the rows in the result set (or close it) before you can issue any other queries on the connection, or an exception will be thrown. 也就是说当通过流式查询获取一个ResultSet后,通过next迭代出所有元素之前或者调用close关闭它之前,不能使用同一个数据库连接去发起另外一个查询,否者抛出异常(第一次调用的正常,第二次的抛出异常)。

总结

在选择MySQL的数据读取方式时,需要根据具体的应用场景和数据集大小来决定:

  • 普通读取适合小型数据集,简单易用,但内存消耗较大。
  • 游标读取适合中型数据集,内存效率较高,逐行处理。
  • 流式读取适合超大数据集,内存占用极低,实时处理能力强,但实现复杂。

根据实际需求,选择合适的读取方式可以提高应用程序的性能和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945065.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【畅购商城】微信支付之支付模块

目录 支付页面 接口 后端实现 前端实现​​​​​​​ ​​​​​​​支付页面 步骤一&#xff1a;创建 flow3.vue组件 步骤二&#xff1a;引入第三方资源&#xff08;js、css&#xff09; <script> import TopNav from ../components/TopNav import Footer from …

如何在 Ubuntu 上安装 PyTorch

简介 PyTorch 因其易用性、动态计算图和高效性而日益流行&#xff0c;成为实现深度学习模型的首选。如果你想探索这个工具并学习如何在 Ubuntu 上安装 PyTorch&#xff0c;本指南将对你有所帮助&#xff01; 在本教程中&#xff0c;我们将引导你完成在 Ubuntu 系统上使用 Pip…

如何设置Edge浏览器访问软件

使用Edge浏览器访问分销ERP A\V系列软件时会出现各种报错&#xff0c;如何设置Edge浏览器使其正常访问&#xff0c;请看下面的具体操作。 一、打开Edge浏览器&#xff0c;点击右上角的 设置及其他&#xff0c;如图&#xff1a; 二、在弹出界面中&#xff0c;点击 扩展&#xff…

ASP.NET Web应用程序出现Maximum request length exceeded报错

一、问题描述 在ASP.NET的web应用中&#xff0c;导出数据时出现500 - Internal server error.Maximum request length exceeded。 二、原因分析 这个错误通常出现在Web应用程序中&#xff0c;表示客户端发送的HTTP请求的长度超过了服务器配置的最大请求长度限制。这可能是因为…

springboot配置oracle+达梦数据库多数据源配置并动态切换

项目场景&#xff1a; 在工作中很多情况需要跨数据库进行数据操作,自己总结的经验希望对各位有所帮助 问题描述 总结了几个问题 1.识别不到mapper 2.识别不到xml 3.找不到数据源 原因分析&#xff1a; 1.配置文件编写导致识别mapper 2.配置类编写建的格式有问题 3.命名…

大数据技术-Hadoop(一)Hadoop集群的安装与配置

目录 一、准备工作 1、安装jdk&#xff08;每个节点都执行&#xff09; 2、修改主机配置 &#xff08;每个节点都执行&#xff09; 3、配置ssh无密登录 &#xff08;每个节点都执行&#xff09; 二、安装Hadoop&#xff08;每个节点都执行&#xff09; 三、集群启动配置&a…

【513. 找树左下角的值 中等】

题目&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出: 7 提示: 二叉树的节点个数的范围是 …

EKF 自动匹配维度 MATLAB代码

该 M A T L A B MATLAB MATLAB代码实现了扩展卡尔曼滤波( E

【小程序】wxss与rpx单位以及全局样式和局部样式

目录 WXSS 1. 什么是 WXSS 2. WXSS 和 CSS 的关系 rpx 1. 什么是 rpx 尺寸单位 2. rpx 的实现原理 3. rpx 与 px 之间的单位换算* 样式导入 1. 什么是样式导入 2. import 的语法格式 全局样式和局部样式 1. 全局样式 2. 局部样式 WXSS 1. 什么是 WXSS WXSS (We…

RSA公钥私钥对在线生成工具--可生成pem,xml,raw等密钥格式

支持生成pkcs8,pkcs1,xml,raw,openssh格式的公钥私钥对&#xff0c;如下图所示&#xff1a; 具体请访问:在线RSA公钥私钥对生成器--生成导出pkcs8/pkcs1 pem证书,raw,xml,openssh等格式,并可指定密钥长度

VMware虚拟机与主机如何传文件

利用Windows局域网的文件夹共享功能。 然后&#xff0c;进入虚拟机文件夹&#xff0c;右键点击网络&#xff0c;映射网络编辑器 输入路径&#xff0c;按照提示登录即可访问

在 React 项目中安装和配置 Three.js

React 与 Three.js 的结合 &#xff1a;通过 React 管理组件化结构和应用逻辑&#xff0c;利用 Three.js 实现 3D 图形的渲染与交互。使用这种方法&#xff0c;我们可以在保持代码清晰和结构化的同时&#xff0c;实现令人惊叹的 3D 效果。 在本文中&#xff0c;我们将以一个简…

TCP 为什么采用三次握手和四次挥手以及 TCP 和 UDP 的区别

1. TCP 为什么采用三次握手和四次挥手 采用三次握手的原因&#xff1a; 确认双方的收发能力。第一次握手&#xff0c;客户端发送 SYN 报文&#xff0c;告诉服务器自身具备发送数据的能力&#xff0c;第二次握手&#xff0c;服务器回应 SYN ACK 报文&#xff0c;表名自己既能…

HarmonyOS NEXT 实战之元服务:静态案例效果---手机查看电量

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; import { authentication } …

机器学习之KNN算法预测数据和数据可视化

机器学习及KNN算法 目录 机器学习及KNN算法机器学习基本概念概念理解步骤为什么要学习机器学习需要准备的库 KNN算法概念算法导入常用距离公式算法优缺点优点&#xff1a;缺点︰ 数据可视化二维界面三维界面 KNeighborsClassifier 和KNeighborsRegressor理解查看KNeighborsRegr…

无需配置设备,借助GitHub快速编译项目并直接运行!

引言 你是否曾经有过类似的烦恼&#xff0c;发现了一个有趣的项目&#xff0c;想要测试一下&#xff0c;但是自己的设备没有对应的开发环境或者受制于自己的设备&#xff0c;不想或者不能去配置对应的开发环境&#xff0c;应该怎么办呢&#xff1f;这种情况下&#xff0c;其实…

【C++11】类型分类、引用折叠、完美转发

目录 一、类型分类 二、引用折叠 三、完美转发 一、类型分类 C11以后&#xff0c;进一步对类型进行了划分&#xff0c;右值被划分纯右值(pure value&#xff0c;简称prvalue)和将亡值 (expiring value&#xff0c;简称xvalue)。 纯右值是指那些字面值常量或求值结果相当于…

k-Means聚类算法 HNUST【数据分析技术】(2025)

1.理论知识 K-means算法&#xff0c;又称为k均值算法。K-means算法中的k表示的是聚类为k个簇&#xff0c;means代表取每一个聚类中数据值的均值作为该簇的中心&#xff0c;或者称为质心&#xff0c;即用每一个的类的质心对该簇进行描述。K-Means算法接受参数K&#xff1b;然后将…

阿里云redis内存优化——PCP数据清理

在阿里云安装了一个redis节点&#xff0c;今天使用时忽然想着点击了一下分析内存。好家伙&#xff0c;居然崩出了一个30多M的块出来。问题是我本地安装的redis没有这个啊&#xff0c;怎么奇怪冒出这个来了。 本着把系统用干榨尽的态度&#xff0c;研究了下这个问题的来源。网上…

Java开发-后端请求成功,前端显示失败

文章目录 报错解决方案1. 后端未配置跨域支持2. 后端响应的 Content-Type 或 CORS 配置问题3. 前端 request 配置问题4. 浏览器缓存或代理问题5. 后端端口未被正确映射 报错 如下图&#xff0c;后端显示请求成功&#xff0c;前端显示失败 解决方案 1. 后端未配置跨域支持 …