java - DB2 插入性能

标签 java db2 db2-luw

我正在尝试从 Excel 文件批量插入 DB/2。 我在 Windows 10 电脑上运行 WildFly 12。 DB/2 运行在 CentOS 7 下的虚拟机上。

使用 POI SAX 方法,读取完整的 250 万条记录的 XLSX 文件需要 80 秒。

我开始在 EJB 程序中使用简单的插入,将文字插入到表中。这花了大约 1.5 小时。

阅读后https://www.idug.org/p/bl/et/blogid=2&blogaid=602我改为使用批处理准备好的语句。我还首先写入全局临时表,最后使用“INSERT INTO SELECT ... FROM”。

关闭自动提交。

最终结果仍需要一个小时,即每秒 750 次插入。

准备元素:

        // get connection using DriverManager class
        try {
            connection = DriverManager.getConnection(
                    "jdbc:db2://192.168.0.5:50000/mydb",
                    "hussain", 
                    "hussain");
        } catch (SQLException e1) {
            out.println("Failed to get connection");
            e1.printStackTrace();
            return;
        }

        // Clear the table
        try {
            Statement statement = connection.createStatement();
            statement.execute("TRUNCATE TABLE " + strMainTable + " IMMEDIATE");
            statement.execute("ALTER TABLE " + strMainTable + " ALTER COLUMN ID RESTART WITH 1 ACTIVATE NOT LOGGED INITIALLY");
            statement.close();
        } catch (SQLException e2) {
            out.println("Failed to clear table<br>");
            e2.printStackTrace();
            return;
        }
        try {
            Statement statement = connection.createStatement();
            statement.execute("DROP TABLE " + strTempTable);
            statement.close();
        } catch (SQLException e2) {
            out.println("Failed to delete table<br>");
        }
        // In DB2:
        // CREATE USER TEMPORARY TABLESPACE USERTEMP MANAGED BY AUTOMATIC STORAGE
        // GRANT USE OF TABLESPACE USERTEMP TO USER HUSSAIN
        try {
            Statement statement = connection.createStatement();
            statement.execute("CREATE GLOBAL TEMPORARY TABLE " + strTempTable + " (" + 
                    " COL1 VARCHAR(900 OCTETS), " + 
                    " COL2 VARCHAR(20 OCTETS), " + 
                    " COL3 VARCHAR(225 OCTETS), " + 
                    " COL4 VARCHAR(500 OCTETS)" + 
                    " ) NOT LOGGED ON COMMIT PRESERVE ROWS ");

            statement.close();
        } catch (SQLException e2) {
            out.println("Failed to create table<br>");
            e2.printStackTrace();
        }

        // Step 2.B: Creating JDBC Statement 
        String sql = "INSERT INTO " + strTempTable + " (COL1, COL2, COL3, COL4) VALUES(?,?,?,?)";
        try {
            statementInsert = connection.prepareStatement(sql);
            connection.setAutoCommit(false);
        } catch (SQLException e1) {
            out.println("Failed to prepare statement<br>");
            e1.printStackTrace();
            return;
        }

然后,在循环中,我读取 XLSX 文件并

            try {
                if(batchRows > 10000) {
                    batchRows = 0;
                    statementInsert.executeBatch();
                }
                //statementInsert.execute();
                batchRows++;
                //lBigBatchRows++;
                statementInsert.addBatch();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

最后:

            Statement statement = connection.createStatement();
            statement.execute("INSERT INTO " + strMainTable + 
                    " (COL1, COL2, COL3, COL4) " +
                    " SELECT COL1, COL2, COL3, COL4 FROM " + strTempTable);
            statement.execute("DROP TABLE " + strTempTable);
            connection.commit();

是的,DB/2 在虚拟机中运行,因此写入速度受到很多因素的影响。尽管如此,750 条记录/秒还是非常慢的。文章作者说他最差的速度是3000/s,最好的是140k/s。如果能靠近就好了。

我还应该注意什么?

最佳答案

您的评论线程提到在可接受的时间内填充未记录的 session 表(声明的全局临时表),但您发现大部分时间都花在从 session 表执行记录的插入到选择上 final table 。

记录的插入比加载慢得多,但有时是唯一的选择。

您还可以使用各种技术来加速 Db2-LUW 上记录的插入速度,这些技术超出了本问题的范围,但 DBA 熟知这些技术。

我的建议是使用 ADMIN_CMD存储过程调用从光标加载操作来填充最终表。

您测试了此方法并发现性能可以接受。

请注意,在 HA 配置中,您需要考虑负载的影响,可能需要使用负载复制或其他方法进行同步或恢复(数据库恢复等)。

如果 Db2 在云服务上运行,则可能还需要重新考虑该方法,具体取决于供应商提供的服务。

关于java - DB2 插入性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58265185/

相关文章:

java - java中的preparedStatement SQL错误

java - LWJGL 3D 渲染不起作用

sql - 将 SQL 编号转换为时间,以执行日期比较

db2 - TABLE 与 TABLESPACE,有什么区别?

Java Connection.setClientInfo 结果 AbstractMethodError

java - java的db2连接问题

java - Dagger 2 - 注入(inject)非 Android 类

sql - 锁定选定的行,以便其他事务在读取时忽略它们

java - 当从 Runtime.getRuntime().exec() 调用新终端时,线程永远不会结束

java - ANT 脚本中的条件任务执行