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

时间:2016-01-30 03:31:23

标签: java sqlite jdbc

我试图为大型IRC频道(Twitch频道)编码系统

我尝试做的其中一件事就是记录每个用户并给他们加入聊天的积分。对于所有意图和目的,聊天只是一个大型IRC频道。我从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 []中选择名称并通过脚本单独运行每个名称。

updateuser看起来像这样:

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,如果没有任何返回,它将是&#39; thisuderdoesntexistforsure)

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

反正。我的问题是;我怎样才能减少它?我遇到了一个需要6分钟更新整个用户列表的问题。拥有2000个在线用户并不罕见,通过while循环将需要2,000个循环才能更新所有用户。该程序更频繁更新,然后不更新。我已经尝试过尽量缩减代码,但我不知道从哪里开始加快速度。

很抱歉,如果我作为傻瓜过来,我对SQL相对较新,这是我在JAVA中最大的项目。

2 个答案:

答案 0 :(得分:1)

您可以使用批处理来执行更新,但在您给定的代码中,更简单的优化是使用一次更新调用(而不是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();
            }
        }
    }
}

答案 1 :(得分:0)

您需要的是batchupdate。一些好的教程可以在互联网上找到。

以下是一个例子:

stm = db.prepareStatement("INSERT INTO ITEM (ID, TYPE, TITEL, UITGELEEND) VALUES (?, ?, ?, ?)");
db.setAutoCommit(false);  
for (int n = 0; n < ItemLijst.getItems().size(); n++) {
    Item huidigItem = ItemLijst.getItemObvIdx(n);
    stm.setString(1, huidigItem.getID().toString());
    stm.setString(2, huidigItem.getType().toString());
    stm.setString(3, huidigItem.getTitel());
    stm.setString(4,String.valueOf(huidigItem.isUitgeleend()));
    stm.addBatch();
 }

String SQL = "UPDATE Employees SET age = 35 " +
         "WHERE id = 100";

//在批处理中添加上面的SQL语句。     stm.addBatch(SQL);     stm.executeBatch();     db.commit();

同时尝试避免加入字符串,而是使用“?”,否则将受到 sql注入攻击

  1. http://tutorials.jenkov.com/jdbc/batchupdate.html
  2. http://www.tutorialspoint.com/jdbc/jdbc-batch-processing.htm