需求是从一个Oracle数据库迁移数据到阿里云数据库HybridDB for PostgreSQL,这样的工作用kettle比较合适。其中一个表数据是600w条左右,从源数据库插入到目标数据库,就这一个表就需要大概3小时左右
Kettle应该有优化的空间,我这边先尝试用Java来实现这个表的迁移。
使用的就是最基础的JDBC连接数据库,需要下载对应的oracle和postgre的jdbc的jar包。
假定Oracle这张表名我们叫source,目标数据库同样已经创建好同样的表了,我们叫target。
- 先从source表查询10w条记录,然后在ResultSet遍历的时候,拼凑一个插入target表的10w条insert语句
格式大概是:
insert into target (column1, column2,...) values (v1-1,v1-2,...);
insert into target (column1, column2,...) values (v2-1,v2-2,...);
...
- 执行 这10w条insert语句。
- 循环1,2步骤分60次处理所有数据
最后测试速度大概插入600w条也需要3个多小时,和kettle持平。
把方案优化一下,把10w条insert语句改成一条insert语句:
- 先从source表查询10w条记录,然后在ResultSet遍历的时候,拼凑一个插入target表的1条insert语句
格式大概是:
insert into target (column1, column2,...) values
(v1-1,v1-2,...),
(v2-1,v2-2,...),
...
- 执行 这1条insert语句。
- 循环1,2步骤分60次处理所有数据
最后测试速度大概插入600w条只需要20分钟左右,速度提高了很多。
主要Java代码如下:
sb.append("insert into interface_item_locator_history (item_id, item_type, org_id, item_org_id, item_class_id, inventory_id, manufactory_id, jyfs, po_tax_rate, so_tax_rate, cost_uc_ti, cost_uc_te, uc_ti, inv_quantity, inv_tc_ti, inv_tc_te, locator_id, inv_date, last_update_date, last_updated_by, creation_date, created_by) values ");
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
interface_item_locator_history obj = new interface_item_locator_history();
BigDecimal item_id = rs.getBigDecimal("item_id");
obj.setItem_id(item_id);
int item_type = rs.getInt("item_type");
obj.setItem_type(item_type);
BigDecimal org_id = rs.getBigDecimal("org_id");
... //更多字段
obj.toSQL(sb);//拼凑insert的sql语句
}
sb.deleteCharAt(sb.length() - 1);
st_pg.execute(sb.toString());
代码可以优化和注意的地方是:
-
StringBuffer构造的时候先设置一个足够大的长度,否则随着lenght的逐渐变大而动态的申请内存会有耗时。
-
ResultSet对象转成自定义的实体类可以使用反射,否则字段一多,需要写很多代码传递值
-
后续还是得尝试优化kettle的速度,用java可以实现,而且灵活,但是需要更多的Java开发工作。
所有源码可以从Git上下载
网友评论