Oracle DB link - where 子句求值

Oracle DB link - where clause evaluation

我有一个 DB2 数据源和一个 Oracle 12c 目标。 Oracle 有一个 DB link 到定义的 DB2,它通常可以正常工作。

现在我在 DB2 中有一个巨大的 table,它有一个用于行更改的时间戳列(我们称之为 ROW_CHANGED)。我想检索在特定时间后更改的行。

运行

SELECT * FROM lib.tbl WHERE ROW_CHANGED >'2016-08-01 10:00:00'

在 DB2 上 returns 恰好在 ca 之后的 1 行。 90 秒很好。

现在我尝试通过 db link:

来自 Oracle 的相同查询

SELECT * FROM lib.tbl@dblink_name WHERE ROW_CHANGED >TO_TIMESTAMP('2016-08-01 10:00:00')

这 运行 持续了几个小时,最终超时。 我阅读了一些 Oracle 文档并找到了分布式查询优化技巧,但其中大部分是指将本地连接到远程 table,这不是我的情况。

无奈之下,我尝试了DRIVING_SITE提示,但没有效果。

现在我想知道何时会计算查询的 WHERE 部分。由于我必须使用 Oracle 语法而不是 DB2 语法进行查询,Oracle 是否有可能首先尝试复制完整的 table 并在之后应用 where 子句?我做了一些研究,但没有找到任何可以帮助我朝这个方向发展的东西。

如果重要的话,ROW_CHANGED 是 DB2 中的一个隐藏列。

感谢任何提前提示。

更新

感谢@all 的帮助。我将分享对我有用的东西。

首先,我使用了 TO_TIMESTAMP,因为 DB2 列也是时间戳(不是日期),我曾期望通过它来规避隐式转换。 如果没有将我 运行 显式转换为 ORA-28534: Heterogeneous Services preprocessing error 并且我没有希望在合理的时间内触及数据库配置。

顺便说一句,解释计划并没有带来太多。它显示了一个完整的提示,并且没有对谓词进行转换。确实它显示 ROW_CHANGED 列为日期,我想知道为什么。

我已尝试 Justins 建议使用绑定变量,但我又遇到了 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 package 强制在远程服务器上评估谓词。这使您可以将查询逐字发送到远程服务器,从而允许您执行诸如使用 DB2 数据库中定义的函数之类的操作。希望在这种情况下,这有点矫枉过正,但如果更简单的解决方案不能足够快地工作,那么将锤子作为备份是很好的。