【问题标题】:SSIS - How to improve a work flowSSIS - 如何改进工作流程
【发布时间】:2015-09-09 19:17:15
【问题描述】:

以前,我曾为我必须面对的情况寻求一种可能的解决方案,以便实现 sql 查询(最初是在 access 中实现的)。我已经找到了一个解决方案(在询问了很多之后),但我想知道是否有人有其他方式来执行这个查询。

我有两个不同的表,一个在 sql 中,另一个在 oracle(S 和 O)中

O(A, B, C) => PK=(A,B) 和 S(D,E,F) => PK = (D,E)

查询如下所示

SELECT A,B,C,E,F
FROM S INNER JOIN O ON
S.D = O.A      (Only one attribute of the PK in O)

S 有超过 10.000 个寄存器,O 有超过 7 亿个。鉴于此,实现合并连接或查找不是逻辑,因为我将只有 D 和 A 之间的第一个匹配项。 所以我认为在Oracle端组装查询会更好。为此,我实施了这样的方案。

使用 sql 我已经执行了这个查询:

with tmp(A) as ( select distinct D as A from S
)
select cast( select concat(' or A = ', A) 
             from tmp 
             for xml path('')) as nvarchar(max)) as ID

我得到一个字符串,其中包含我要在 oracle 上搜索的值。 最后在数据流中,我创建了一个这样的表达式:

select A, B, C
from O
where A= '' + @ID

我将这些值下载到 sql server,然后我可以随意操作它们。

foreach 循环的使用是必要的,因为我将 sql 字符串存储在对象变量中。我发现 SSIS 在 nvarchar(max) 变量方面存在一些问题。

一些注意事项:

1) Oracle 数据库由公司的另一个部门管理,他们只授予对表的读取权限。

2) sql server的DBA不允许下载暂存区的O表。没有与他谈判的可能性,此外,这个表每天都会更新更多的寄存器。他只管理这台服务器,对 Oracle 没有任何权限。

3) 为我团队的一些成员提供的解决方案是在 oracle 中在不同表之间创建一个查询,该查询可以为我提供我需要的 O 属性,结果我可以获得超过 300 万个寄存器并不是所有的属性 A 都出现在 S 中。而且,D 的一些值已经被操纵,所以它们可能不会出现在 O 中。

通过这个实现,我从 Oracle 获得了超过 150.000 个寄存器。但我想知道是否可以实施另一种解决方案,或者是否可以使用其他组件来达到相同的结果。相信我,我之前已经阅读、询问和搜索了很多内容来实施此流程。

【问题讨论】:

    标签: sql-server oracle join ssis


    【解决方案1】:

    已编辑:

    选项 1(你说你不能使用这个解决方案——但它会是第一个——最好的)

    使用 DBLink 让 Oracle 访问 S 表(必须使用 Oracle 数据库网关)。在Oracle Joining O 和S 中创建一个视图。最后使用链接服务器让SQL Server 访问Oracle Joining 视图并得到结果。

    流程如下:

    选项 2(你说你不能使用这个解决方案 - 但它会是第二个)

    因为您的 Oracle 管理员似乎是怪物,如果他们抓住您的爪子就会杀死您。然后您可以尝试(如果他们让您在 oracle 中创建表):

    • 在 SQL Server 中创建链接服务器(从 SQL 访问 Oracle 服务器)。正如我在“正常情况”中提到的那样。
    • 并在 Oracle 模式中创建一个(临时)表,只有 1 列(它将存储来自 SQL Server 的 D 值)

      每次您需要在 SQL Server 中评估查询时执行:

      插入 ORACLE_LINKED_SERVER.ORACLE_OWNER.TEMP_TABLE 从 S 中选择不同的 D;

      SELECT * FROM OPENQUERY('SELECT * FROM ORACLE_OWNER.O WHERE A IN (SELECT D FROM ORACLE_OWNER.TEMP_TABLE)');

      最后别忘了删除 Oracle 的临时表:

      DELETE * FROM ORACLE_LINKED_SERVER.ORACLE_OWNER.TEMP_TABLE;

    选项 3(如果您有 Oracle 许可证和一台可用主机)

    您可以在主机中安装自己的 Oracle 服务器并使用选项 2。

    选项 4

    如果您的解决方案确实是唯一的出路,那么让我们尝试对其进行一些改进。

    如您所知,您的解决方案有效,但它有点激进(您正在将关系代数半连接运算符转换为具有怪物条件的关系代数选择运算符)。您说 Oracle 表每天都会更新更多寄存器,但是如果您的表的更新率低于您的查询率,那么您可以创建一个结果缓存,您可以在表 S 或 O 不变的情况下使用它。

    按如下方式进行:

    在您的 SQL Server 中创建一个表来存储您的怪物查询的 Oracle 结果。在构建和启动您的查询之前,请执行以下操作:

    SELECT last_user_update
      FROM sys.dm_db_index_usage_stats
      WHERE database_id = DB_ID( 'YourDatabaseName')
            AND OBJECT_ID=OBJECT_ID('S')
    

    这将返回最近一次更新表 S 的时间。将此值存储在表中(创建新表或将此值存储在典型参数表中)。

    创建你的怪物查询。但在启动它之前,请将此查询发送到 Oracle:

    SELECT MAX(ORA_ROWSCN) 
      FROM O;
    

    它返回导致表更改的最后一个 SCN(系统更改编号)。将此值存储在表中(创建新表或将此值存储在典型参数表中)。

    启动大查询并将其结果存储到缓存表中。

    最后,当你需要重复大查询时,首先在你的 SQL Server 中执行:

    SELECT last_user_update
      FROM sys.dm_db_index_usage_stats
      WHERE database_id = DB_ID( 'YourDatabaseName')
            AND OBJECT_ID=OBJECT_ID('S')
    

    并在 Oracle 中执行:

    SELECT MAX(ORA_ROWSCN) 
      FROM O;
    

    如果一个或两个值相对于您存储在参数表中的值发生了变化,那么您必须将它们存储在参数表中(更新旧值)并再次启动大查询。但是,如果没有任何值发生变化,那么您的缓存是最新的,您可以使用它。

    注意

    【讨论】:

    • 非常感谢您的回答。但正如我所说,与 Oracle 数据库的人员或我的 DBA 谈判是不可能的。问候
    • @d2907 我已经编辑了答案以包含一个新案例(没有 Oracle 网关),但它假设您可以在 oracle 中有 1 个表从 SQL Server 插入数据。有可能吗?
    • 如你所说,它们可能是大“怪物”。我花了很多时间才找到这个解决方案,因为他们可以对数据库提出所有限制和问题。在 Oracle 中,我不能什么都不做,也不能向他们寻求一些“帮助”。再次感谢。
    • @d2907 如果我理解了,您可以在 WHERE 子句中创建一个具有所有不同 SD 值的怪物选择,如 A = val1 OR A = val2 OR VAL=val3... OR VAL=val1432... 并发送它给甲骨文。我理解了吗?
    • 没错。我正在创建一个包含或多或少 2000 个值的选择,但我避免下载超过 300 万个寄存器。
    猜你喜欢
    • 2021-04-05
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多