我有一个java程序,用于比较数据并将数据从本地Oracle数据库移动到由在线供应商托管的外部MS SQL数据库。
目前,程序连接到执行SELECT * FROM myTABLE
的MS SQL数据库,并将结果放在二维数组中。然后在Oracle中创建临时表,并使用for循环将数据插入临时表:
for (int ii = 0; ii < arr.length(); ii++){
query = "insert into myTable_temp values "+values_from_array;
stmt.executeQuery();
}
使用MINUS
语句查找差异:
query = "select * from ora_table minus select * from myTable_temp";
rs = stmt.executeQuery();
然后使用insert_into_mssql()方法将结果插回到MS SQL表中:
while (rs.next()){
query = "insert into myTable values "+ values_from_rs
insert_into_mssql(query);
}
除了我使用的表有220,000行外,这个工作正常。因此,加载数组,插入临时表,运行减去语句,然后将所有内容重新插入到mssql表中需要很长时间。
有更有效的方法吗?还是一种让它更快的方法? (dblink或任何直接连接都不会有安全限制)
答案 0 :(得分:3)
答案 1 :(得分:2)
我认为创建dblink是个好主意。
答案 2 :(得分:1)
也许它可以帮助你。
Statement的新addBatch()方法允许您将多个更新语句作为一个单元组合并立即执行它们。在创建语句之后和执行之前调用addBatch():
con.setAutoCommit(false); // If some fail, we want to rollback the rest
Statement stmt = con.createStatement( );
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (1, "J Smith", "617 555-1323");
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (2, "A Smith", "617 555-1132");
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (3, "C Smith", "617 555-1238");
stmt.addBatch(
"INSERT INTO CUSTOMERS VALUES (4, "K Smith", "617 555-7823");
int[] upCounts = stmt.executeBatch( );
con.commit( );
请注意,我们会在创建批处理之前关闭事务自动提交。
答案 3 :(得分:0)
我可能会先将它加载到数组中,然后使用与写出时相似的技术。还可以看看并行化插入。
如果我从头开始这样做,我会将所有Oracle数据带到SQL Server并执行所有操作(从Oracle复制表,查找差异并插入SQL Server,删除从Oracle复制的表)而不是全部SQL Server数据到Oracle,只转储新记录并将它们带到SQL Server并插入它们。
SQL Server也有一个非常好的ETL工具 - SQL Server Integration Services,但除了SQL Server数据源和目标之外,我还没有很多成功使用它。
答案 4 :(得分:0)
考虑到技术限制(没有dblinks等),您可以尝试降低传输开销。 这可以通过维护同步状态和仅传输更新的行来完成。
如果我理解正确,您只需要将Oracle数据库中的更新行和新行传输到MS SQL。在非常通用的变体中,您需要在oracle_table
中添加2列,其中包含复制状态:
last_update_time
- 由插入或更新每个行的触发器维护。触发将列值设置为每行更改的当前日期和时间以及新行。
last_sync_time
- 由插入触发器维护并由同步应用程序更改。
对于新行last_update_time := sysdate
和last_sync_time := last_update_time - 1
。
按当前日期时间更新的每个oracle_table
行更新last_update_time
。
在每个同步会话中执行下一个序列:
从oracle_table
中选择last_sync_time < last_update_time
的所有行,并将其插入到Oracle服务器上的某个缓冲区表中:
begin
execute immediate 'truncate table buffer_table';
insert into buffer_table(...)
select * from oracle_table where last_sync_time < last_update_time;
end;
将所有行从buffer_table传输到MS SQL服务器并相应地更新myTable
。
将所有已同步行的更新时间提前到新值:
update
oracle_table o_table
set
last_sync_time = ( select buf_table.last_update_time
from buffer_table buf_table
where buf_table.Primary_Key = o_table.Primary_Key
)
where
o_table.Primary_Key in (select Primary_Key from buffer_table)
请注意,在同步过程中可能会更改同步行,并且在更新buffer_table
时我们需要last_sync_time
的时间戳值。
P.S。我认为MS SQL端的数据库是只读的。双向同步可以在相同的原理上完成,略有算法改进。