我有一个DB2数据源和一个Oracle 12c目标。Oracle有一个DB链接到DB2定义的正常工作。
现在我在DB2中有一个巨大的表,它有一个用于行更改的时间戳列(我们称之为ROW_CHANGED)。我想检索在特定时间后发生更改的行。
运行 SELECT * FROM lib.tbl WHERE ROW_CHANGED >'2016-08-01 10:00:00'
在大约90秒后返回1行,这很好。
现在我尝试从Oracle通过db链接相同的查询:
SELECT * FROM lib.tbl@dblink_name WHERE ROW_CHANGED >TO_TIMESTAMP('2016-08-01 10:00:00')
此操作将运行数小时并以超时结束。我读了一些Oracle文档,找到了分布式查询优化技巧,但大多数都是关于将本地表连接到远程表,而不是我的情况。
在绝望中,我尝试了DRIVING_SITE提示,但没有效果。
现在我想知道查询的WHERE部分何时会被评估。由于我必须使用Oracle语法而不是DB2语法查询,是否有可能Oracle将尝试先复制完整的表,然后应用where子句?我做了一些调查,但没有找到任何对我这个方向有帮助的。
ROW_CHANGED是DB2中的一个隐藏列。
谢谢你的提示。
Thanks@all寻求帮助。我将分享我是如何做到这一点的。
首先,我使用了TO_TIMESTAMP,因为DB2列也是时间戳(而不是日期),并且我希望通过这种方式来规避隐式转换。没有显式转换,我遇到了ORA-28534: Heterogeneous Services preprocessing error
,我没有希望在合理的时间内触摸DB配置。
解释计划并没有带来什么。它显示了一个FULL提示,谓词上没有转换。确实,它显示ROW_CHANGED列为Date,我想知道为什么。
我已经尝试贾斯汀的建议使用绑定变量,但我又得到ORA-28534。接下来我要做的是把它封装到pl/sql块中(以后会在SP中运行)。
declare
v_tmstmp TIMESTAMP := 01.08.16 10:00:00;
begin
INSERT INTO ORAUSER.TMP_TBL (SRC_PK,ROW_CHANGED)
SELECT SRC_PK,ROW_CHANGED
FROM lib.tbl@dblink_name
WHERE ROW_CHANGED > v_tmstmp;
end;
这与在DB2本身中执行的时间相同。这里的日期格式是DD.MM.YY,因为它是默认的。将变量赋值更改为
时v_tmstmp TIMESTAMP := TO_TIMESTAMP('01.08.16 10:00:00','DD.MM.YY HH24:MI:SS');
我遇到了和以前一样的问题。
同时,DB2操作符已经在ROW_CHANGED列中创建了我当天早些时候请求的索引。这似乎基本上解决了问题。现在连我原来的查询都快完成了
如果您实际使用Oracle特定的转换函数,如to_timestamp
,则强制在Oracle端对谓词进行计算。Oracle不知道如何将内置函数(如to_timestamp
)转换为DB2中完全等价的函数调用。
如果使用绑定变量,则更有可能在DB2端求值。但是,由于不同数据库之间的数据类型映射,这可能会变得复杂——在一个引擎的date
和另一个引擎的timestamp
数据类型之间可能没有完美的映射。如果这是一个数字列,那么绑定变量几乎肯定会被推入。在这种情况下,可能需要进行一些操作,以确定为您的框架、Oracle和DB2工作的变量使用哪种数据类型。
如果使用绑定变量不起作用,您可以使用dbms_hs_passthrough
包强制在远程服务器上计算谓词。这样就可以将查询逐字逐句地发送到远程服务器,从而可以执行使用DB2数据库中定义的函数之类的操作。在这种情况下,这可能有点小题大做,但如果更简单的解决方案不能快速工作,那么使用锤子作为备份是很好的。