【cursor】大数据量操作

发布时间 2023-05-28 11:32:15作者: aaacarrot

cursor 是什么

数据库 Cursor(游标)是一种可编程的数据库对象,用于在查询结果集中遍历和操作数据。通过使用 Cursor,我们可以在数据库中执行 SQL 查询、检索数据和对数据进行更新、插入或删除等操作。在使用 Cursor 时,首先要创建一个 Cursor 对象,并将其与一个查询关联。随后,可以使用游标方法来检索数据,该方法可以使用循环结构反复调用,以遍历整个结果集。

使用 Cursor 可以灵活地访问数据库,使得在程序设计中可以更加方便地完成各种数据操作任务。
例如,
可以使用 Cursor 对象执行动态查询,在查询结果中获取特定字段或行,
也可以使用 Cursor 更新或删除数据库中的数据。
同时可以使用 Cursor 还可以实现批量数据的插入或者更新等高级数据库操作。

抽一下重点,cursor 可以做:

  • 动态查询,在查询结果中获取特定字段或行
  • 更新或删除数据库中的数据
  • 批量插入或更新等

嗯,听起来真香。

所以,说的这些东西,mybatis 也可以做啊,为什么还有cursor 啥事呢?毕竟现在基本都在用mybatis/mybatis plus 之类的ORM框架了。

SO, 区别是啥,cursor 有什么优势(mybatis 做不到的东西,cursor却可以做得到的)呢?

与使用MyBatis SQL查询10000条相比,使用largeDataCursor的优势主要有以下几点:

  1. 更低的系统资源消耗:使用largeDataCursor时,只有当需要处理数据时才会从数据库中读取数据,而且一次只读取很少的数据,因此能够更有效地利用系统资源,并减少对数据库的压力。

  2. 更高的处理效率:使用largeDataCursor时,处理大量数据时不需要一次将所有数据都从数据库中拿出来,只需要按需获取,这样可以更快地完成数据的处理,并减少代码逻辑的复杂度。

  3. 更好的扩展性:使用largeDataCursor时,由于可以动态地调整游标的位置,因此可以更容易地处理不同数量级的数据,并具有更好的扩展性和可维护性。

总的来说,虽然MyBatis SQL查询也可以实现类似的功能,但如果需要处理大量数据或数据量不断增长的场景,使用largeDataCursor会更加高效、稳定,形成较好的系统解决方案。

MyBatis框架在进行数据查询时,的确是需要将查询结果全部加载到内存中,当然如果数据量不大,内存占用也不会太大。但如果数据量比较大时,这种方式会导致内存消耗过高,影响系统的性能。而使用largeDataCursor在处理数据时,只有当需要处理某条记录时才会从数据库中读取这条记录,因此能够有效地降低内存的消耗。

在largeDataCursor查询的过程中,数据库服务器会在内部建立一个游标,按需返回指定数量的数据给客户端,基本上不会一次性返回所有记录。即使在需要遍历所有记录的情况下,也可以通过循环逐条读取数据,而不必一次读取全部数据。因此,相对于MyBatis框架,使用largeDataCursor能够更好的处理大量数据,并减轻内存压力。

当然,要实现较高效的查询处理,还需要根据具体业务场景进行合理的SQL编写、索引建立和分页等操作,以充分发挥largeDataCursor的优势。

虽然现在不太使用存储过程
而对于大量数据的处理,可以使用类似largeDataCursor的技术,这样可以更高效、灵活地处理数据,降低内存消耗,并且可以避免存储过程的一些问题和限制。




一个关于cursor的小示例

import java.sql.*;

public class CursorExample {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            // 建立数据库连接
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "root", "password");
            conn.setAutoCommit(false); // 关闭自动提交

            // 创建 Cursor 对象
            stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            rs = stmt.executeQuery("SELECT * FROM my_table");

            // 使用 Cursor 遍历查询结果
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");

                // 对查询结果进行修改
                rs.updateString("name", name + "_modified");
                rs.updateInt("age", age + 1);
                rs.updateRow();
            }

            conn.commit(); // 提交事务,将修改写入数据库
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                if (conn != null) {
                    conn.rollback(); // 回滚事务
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            // 关闭结果集、语句和数据库连接
            try {
                if (rs != null) {
                    rs.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}