DB2 插入性能
DB2 insert performance
我正在尝试从 Excel 文件批量插入 DB/2。
我的 运行 WildFly 12 在我的 Windows 10 PC 上。 DB/2 在 CentOS 7 下的 VM 上是 运行。
使用POI SAX方法,读取250万条记录的完整XLSX文件需要80秒。
我开始在我的 EJB 程序中使用简单的插入,将文字插入 table。这花了大约 1.5 小时。
阅读https://www.idug.org/p/bl/et/blogid=2&blogaid=602后,我改为使用批处理准备语句。我也首先写一个全局临时 Table,最后使用 "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 在 VM 中是 运行,因此写入速度受很多因素影响。尽管如此,每秒 750 条记录还是非常慢。文章作者说他最差的速度是3000/s,最好的是140k/s。能亲近就好了。
我还应该看什么?
您的评论线程提到在 acceptable 时间内填充未记录的会话 table(声明为全局临时 table),但您发现大部分经过的时间是花费了从会话 table 到最终 table 的记录插入到 select 中的时间。
记录的插入比加载慢得多,但有时是唯一的选择。
您还可以使用各种技术加速 Db2-LUW 上的记录插入,这些技术超出了这个问题的范围,但 DBA 众所周知。
我的建议是使用 ADMIN_CMD 存储过程调用从游标加载操作来填充最终的 table。
您测试了这种方法,发现性能可以接受table。
请注意,在 HA 配置中,您需要考虑负载的影响,可能需要使用 load copy
或其他同步或恢复方法(数据库还原等)。
如果 Db2 运行 在云服务上,则可能还需要重新考虑该方法,具体取决于供应商提供的内容。
您可以关闭将插入记录到主 table。
改变 table main_table 激活最初未记录。
在您提交之前,该设置将一直保留。
如果您可以将 excel 导出为以逗号分隔的文件,您可以使用更快的加载命令。
更改您的 strmaintable Id 列缓存 1000,无顺序。
id integer not null 默认生成为identity(从1开始,递增1,缓存1000,无序)
https://developer.ibm.com/technologies/databases/articles/dm-0403wilkins/#table5
我正在尝试从 Excel 文件批量插入 DB/2。 我的 运行 WildFly 12 在我的 Windows 10 PC 上。 DB/2 在 CentOS 7 下的 VM 上是 运行。
使用POI SAX方法,读取250万条记录的完整XLSX文件需要80秒。
我开始在我的 EJB 程序中使用简单的插入,将文字插入 table。这花了大约 1.5 小时。
阅读https://www.idug.org/p/bl/et/blogid=2&blogaid=602后,我改为使用批处理准备语句。我也首先写一个全局临时 Table,最后使用 "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 在 VM 中是 运行,因此写入速度受很多因素影响。尽管如此,每秒 750 条记录还是非常慢。文章作者说他最差的速度是3000/s,最好的是140k/s。能亲近就好了。
我还应该看什么?
您的评论线程提到在 acceptable 时间内填充未记录的会话 table(声明为全局临时 table),但您发现大部分经过的时间是花费了从会话 table 到最终 table 的记录插入到 select 中的时间。
记录的插入比加载慢得多,但有时是唯一的选择。
您还可以使用各种技术加速 Db2-LUW 上的记录插入,这些技术超出了这个问题的范围,但 DBA 众所周知。
我的建议是使用 ADMIN_CMD 存储过程调用从游标加载操作来填充最终的 table。
您测试了这种方法,发现性能可以接受table。
请注意,在 HA 配置中,您需要考虑负载的影响,可能需要使用 load copy
或其他同步或恢复方法(数据库还原等)。
如果 Db2 运行 在云服务上,则可能还需要重新考虑该方法,具体取决于供应商提供的内容。
您可以关闭将插入记录到主 table。
改变 table main_table 激活最初未记录。
在您提交之前,该设置将一直保留。
如果您可以将 excel 导出为以逗号分隔的文件,您可以使用更快的加载命令。
更改您的 strmaintable Id 列缓存 1000,无顺序。
id integer not null 默认生成为identity(从1开始,递增1,缓存1000,无序)
https://developer.ibm.com/technologies/databases/articles/dm-0403wilkins/#table5