java - 如何加快Java(JDBC)中大量SQL更新的执行速度

标签 java sqlite jdbc

我正在尝试为大型 IRC channel (Twitch Channel)编写系统

我想做的一件事是记录每个用户并为他们参与聊天提供积分。无论如何,聊天只是一个大型 IRC channel 。我正在从 twitch API 检索一个大列表中的用户,我将所有用户名放入一个大数组中,并使用 while 循环运行以下计时器:

        timer = new Timer(900000, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            updating = true;
            try {
                Arraynumber = 0;
                TwitchBot.getDate();
                arrayused = false;
                System.out.println("trying to save users if theres enough stuff");
                while(Arraynumber < TwitchBot.words.length){
                    TwitchBot.CheckUpdateUserSQL(TwitchBot.words[Arraynumber]);
                    Arraynumber++;
                    System.out.println("updating database");
                }
            } catch (ClassNotFoundException e) {

                e.printStackTrace();
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
        }
    });

正如您所看到的,这是一个简单的计时器,它从 String[] 中选取名称并通过脚本单独运行每个名称。

更新用户看起来像这样:

public static void CheckUpdateUserSQL(String sqluser) throws ClassNotFoundException{
        selectSQL(sqluser);
        if (id == "thisuserdoesntexistforsure"){
            InsertSQL(sqluser);
        }
        else{
            int progress = CurrentTime - lastlogin;
            int totalprogress = progress + totaltime;
        if(progress < 60 && progress > 0){
            c15 = null;
            Statement stmt = null;
                if(isonline == 1) {
                    coins = progress / 4;
                }
                else{
                    coins = progress / 5;
                }
                int coinsincrease = (int) Math.ceil(coins);
                int coinstotal = coinsamount + coinsincrease;
              Class.forName("org.sqlite.JDBC");
              try {
                c15 = DriverManager.getConnection("jdbc:sqlite:users.db");
                c15.setAutoCommit(false);
                stmt = c15.createStatement();
                String sql = "UPDATE USERS set TOTALTIME = " + totalprogress + " where NAME='" + sqluser + "';";
                stmt.executeUpdate(sql);
                c15.commit();
                String sql2 = "UPDATE USERS set LASTLOGIN = " + CurrentTime + " where NAME='" + sqluser + "';";
                stmt.executeUpdate(sql2);
                c15.commit();
                String sql3 = "UPDATE USERS set TOTALCOIN = " + coinstotal + " where NAME='" + sqluser + "';";
                stmt.executeUpdate(sql3);
                c15.commit();
                String sql4 = "UPDATE USERS set ISONLINE = 0 where NAME='" + sqluser + "';";
                stmt.executeUpdate(sql4);
                  c15.commit();
                  stmt.close();
                  c15.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            }
            else {
                Connection c = null;
                Statement stmt = null;
                try {
                    c = DriverManager.getConnection("jdbc:sqlite:users.db");
                     c.setAutoCommit(false);
                        stmt = c.createStatement();
                        String sql2 = "UPDATE USERS set LASTLOGIN = " + CurrentTime + " where NAME='" + sqluser + "';";
                        stmt.executeUpdate(sql2);
                        c.commit();
                          stmt.close();
                          c15.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        }
    }

此代码检查用户是否存在。 (使用 select 方法,这是我能得到的最简洁的方法,它只搜索用户名并返回 id,如果没有返回,则该 id 将为“thisuderdoesntexistforsure”)

如果用户存在,它将运行代码来计算他们的在线时间以及自上次访问以来在线时间和积分的增加。然后更新代码。如果他们不在线或者时间以某种方式返回负值(或太高),它将仅更新时间戳并跳过其余更新。这可以确保离开一天的用户在第二天登录 5 分钟时不会仅仅获得 1.400 分钟的在线时间。

无论如何。我的问题是;我怎样才能把它修剪下来?我遇到一个问题,更新整个用户列表需要 6 分钟。拥有 2000 个在线用户并不罕见,需要执行 2000 次 while 循环才能更新所有用户。该程序更新的频率比不更新的频率高。我尝试过尽可能精简代码,但我不知道从哪里开始加快速度。

抱歉,如果我显得很白痴,我对 SQL 还比较陌生,这是我在 JAVA 方面迄今为止最大的项目。

最佳答案

您可以使用批处理来执行更新,但在给定的代码中,一种更简单的优化是通过一次更新调用(而不是 4 次)来更新值。另外,您可以使用 PreparedStatementtry-with-resources close 。比如,

public static void CheckUpdateUserSQL(String sqluser) throws ClassNotFoundException {
    selectSQL(sqluser);
    if (id.equals("thisuserdoesntexistforsure")) {
        InsertSQL(sqluser);
    } else {
        String sql = "UPDATE USERS set TOTALTIME = ?, LASTLOGIN = ?, "
                + "TOTALCOIN = ?, ISONLINE = 0 where NAME = ?";
        String sql2 = "UPDATE USERS set LASTLOGIN = ? where NAME=?";
        int progress = CurrentTime - lastlogin;
        int totalprogress = progress + totaltime;
        if (progress < 60 && progress > 0) {
            if (isonline == 1) {
                coins = progress / 4;
            } else {
                coins = progress / 5;
            }
            int coinsincrease = (int) Math.ceil(coins);
            int coinstotal = coinsamount + coinsincrease;
            Class.forName("org.sqlite.JDBC");
            try (Connection conn = DriverManager.getConnection("jdbc:sqlite:users.db");
                    PreparedStatement ps = conn.prepareStatement(sql)) {
                ps.setInt(1, totalprogress);
                ps.setInt(2, CurrentTime);
                ps.setInt(3, coinstotal);
                ps.setString(4, sqluser);
                ps.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } else {
            Class.forName("org.sqlite.JDBC");
            try (Connection conn = DriverManager.getConnection("jdbc:sqlite:users.db");
                    PreparedStatement ps = conn.prepareStatement(sql2)) {
                ps.setInt(1, CurrentTime);
                ps.setString(2, sqluser);
                ps.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

关于java - 如何加快Java(JDBC)中大量SQL更新的执行速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35097661/

相关文章:

c++ - 如果我删除一些 "special"SQLite 表会发生什么

java - JDBC连接: Access Denied for User even All Previlleges are Granted

java - 一对多 Spring 结果映射

java - 在 Android 应用程序中共享 ArrayList<Custom>

java - Spring : Using Interface as RequestBody and returning the right class

java - 查询生成器中的 JPA 2.0 谓词条件列表

java - Java 中的什么在虚拟内存中使用 400M,我如何降低该使用量?

java - 在应用程序启动时创建 SQLite 数据库

SQL 更新查询中的 Python 变量

java - resultset.getObject 上的 AbstractMethodError