【问题标题】:Splitting a massive table with BLOBS over DB Link in Oracle在 Oracle 中通过 DB Link 使用 BLOBS 拆分海量表
【发布时间】:2015-09-05 07:47:02
【问题描述】:

我有一个有趣的问题。我正在将数据从一个数据库迁移到另一个数据库,其中包括数百万个 BLOB,其元数据实际上相当于 TB 的数据。 由于许多原因,这必须通过 DB Link 完成,并且包含 BLOB 的另一侧的视图未编入索引。这是因为没有一个唯一的密钥,并且存在复杂的逻辑 唯一标识文档(只是我们迁移到新系统的一个原因)。我想做的是:

1) 将行拆分为单独的块进行传输,这样我就可以并行访问,而且如果发生崩溃我也不会丢失所有内容 2)插入临时表 3) 一切都结束后,我会将临时表合并到生产表中并转储临时表

由于 Oracle 对通过 DB 链接的 LOB 引用的限制,我无法在视图上打开游标。 我使用 insert into 来绕过 Oracle 限制,但我确实需要对行进行切片。我曾多次尝试运行我的脚本,但我的会话会在 2 天后被终止,我失去了一切。

我尝试通过 rownum 对其进行分块以使用分页之类的分块,但它不起作用。这是我的代码(来自http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html 的帮助):

-- for second chunk
procedure process_chnk_2 (
    l_slice     pls_integer;
)   
begin
    execute immediate 'insert /*+ append */ into DESTINATION_TABLE
                        select *
                            from 
                            ( select q.*
                                    ,rownum rnum
                                from
                                ( select *
                                    from migr_view.MIGR_BLOB@DB_LINK) q
                                where rownum <= l_slice * 2
                            ) where rnum >= l_slice
                        ';
    commit;
end process_chnk_2;

这不起作用,因为您仍需要使用 BLOB 进行查询。

我曾想过选择其中一个文本列,然后像这样加入原始视图:

-- for second chunk
procedure process_chnk_2 (
    l_slice     pls_integer;
)   
begin
    execute immediate 'insert /*+ append */ into DESTINATION_TABLE
                        select *
                            from 
                            ( select q.text_that_is_not_quite_a_key
                                    ,q.second_that_is_not_quite_a_key
                                    ,q.third_that_is_not_quite_a_key
                                    ,q.fourth_that_is_not_quite_a_key
                                    .
                                    .
                                    .
                                    ,rownum rnum
                                from
                                ( select *
                                    from migr_view.MIGR_BLOB@DB_LINK) q
                                where rownum <= l_slice * 2
                            ) z
                            , migr_view.MIGR_BLOB@DB_LINK x
                            where z.rnum >= l_slice
                              and z.text_that_is_not_quite_a_key = x.text_that_is_not_quite_a_key
                              and z.second_that_is_not_quite_a_key = x.second_that_is_not_quite_a_key
                              and z.third_that_is_not_quite_a_key = x.third_that_is_not_quite_a_key
                              and z.fourth_that_is_not_quite_a_key = x.fourth_that_is_not_quite_a_key
                              .
                              .
                              .
                        ';
    commit;
end process_chnk_2;

但是,我们正在讨论加入一个包含数百万行且没有索引的表只是为了获取切片...您知道这需要多长时间吗?

我不能使用工具,甚至不能使用数据泵……只能使用脚本…… 感谢您的帮助!

【问题讨论】:

  • 当您说“这不起作用,因为您仍需要使用 BLOB 进行查询”时,您是什么意思。 ?您的页码算法也不太正确-您每次都会带来 l_slice 行,这意味着它每次都会变大-最终非常大。那一点需要更像where rownum &lt;= l_slice * 1000 ) where rnum &gt; ((l_slice-1)*1000)——一次会带来超过 1000 行
  • 您能否在 JDBC 上使用 Java 程序而不是 DB 链接 - 这样可以绕过 DB 链接限制。从源数据库的角度来看,无论是通过数据库链接还是 JDBC,都无关紧要。您还可以避免数据库链接到实际完成过滤的位置的模糊性。对于拆分,您只需要一组“关键”值,这些值可以为您提供合理均匀的拆分,然后将其赶走。我不确定我是否会依赖 rownum - 没有为特定“rownum”排序的实际行在不同的运行中可能会有所不同(有足够的基础更改)。
  • 从最后的评论继续 .. 另一个选项,如果可以同意的话,我认为是说服源数据库允许数据泵或自定义提取写入单独文件系统上的文件,可以卸载然后重新安装在目标上。这节省了大量的网络流量。您可以变得可爱并拥有多个这样的“摆动 LUN”,这样您就可以并行运行提取和加载。
  • @TenG - 感谢您的 cmets。为此,我会比 JDBC 更快地使用 Data Pump,但是为了能够使用标准的 Oracle 工具,我需要经历比仅按顺序加载它所花费的更长的时间……这个项目不是由开发人员;(
  • @GregHNZ - 我的意思是你仍然需要通过(从 migr_view.MIGR_BLOB@DB_LINK 中选择 *)这是不允许的......关于你的其他评论,我同意 - 我会尝试现在重写它

标签: sql database plsql oracle11g blob


【解决方案1】:

我在过去两天里尝试把这个想法放在一起——我只是提出它作为一个答案,但我想听听你的建议,因为这很丑!!虽然我们无法以任何排序顺序识别唯一键,但通过混合键和提取数字,我们实际上可以找到要切片的值范围,并且分布相当均匀。

  l_stmt := q'{insert /*+ NOLOGGING NOWAIT */  
          into  DESTINATION_TABLE
          select *
          from   migr_view.migr_blob@DB_LINK
          where  to_number(regexp_substr(not_key_1 || not_key_2 || not_key_3..., 
          '[[:digit:]]+')) >= }' || i_start_slice || q'{ 
          and to_number(regexp_substr(not_key_1 || not_key_2 || not_key_3..., 
          '[[:digit:]]+')) <  }' || l_end_slice;

【讨论】:

    猜你喜欢
    • 2019-01-20
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 2011-10-27
    相关资源
    最近更新 更多