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 数据库中定义的函数之类的操作。希望在这种情况下,这有点矫枉过正,但如果更简单的解决方案不能足够快地工作,那么将锤子作为备份是很好的。
我有一个 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 数据库中定义的函数之类的操作。希望在这种情况下,这有点矫枉过正,但如果更简单的解决方案不能足够快地工作,那么将锤子作为备份是很好的。