跨 dblink 选择并插入

发布于 2024-08-25 15:57:58 字数 677 浏览 12 评论 0原文

我在 Oracle 10 中通过 dblink 进行 select into insert 时遇到了一些麻烦。我使用以下语句:

INSERT INTO LOCAL.TABLE_1 ( COL1, COL2) 
SELECT  COL1, COL2
FROM REMOTE.TABLE1@dblink s
WHERE COL1 IN ( SELECT COL1 FROM WORKING_TABLE)

当我运行该语句时,以下是针对 DB Link 上的远程服务器运行的内容:

SELECT /*+ OPAQUE_TRANSFORM */ "COL1", "COL2"
FROM "REMOTE"."TABLE1" "S"

如果我运行仅选择而不执行插入到以下运行中:

SELECT /*+ */ "A1"."COL1"
     , "A1"."COL2"
  FROM "REMOTE"."TABLE1" "A1"
 WHERE "A1"."COL1" =
   ANY ( SELECT "A2"."COL1"
       FROM "LOCAL"."TABLE1"@! "A2")

问题是在插入情况下,整个表正在通过 dblink 拉出,然后限制本地,考虑到表大小,这需要相当多的时间。添加插入物是否有任何原因会以这种方式改变行为?

I am having a bit of trouble with a select into insert across a dblink in oracle 10. I am using the following statement:

INSERT INTO LOCAL.TABLE_1 ( COL1, COL2) 
SELECT  COL1, COL2
FROM REMOTE.TABLE1@dblink s
WHERE COL1 IN ( SELECT COL1 FROM WORKING_TABLE)

When I run the statement the following is what gets run against the remote server on the DB Link:

SELECT /*+ OPAQUE_TRANSFORM */ "COL1", "COL2"
FROM "REMOTE"."TABLE1" "S"

If I run the select only and do not do the insert into the following is run:

SELECT /*+ */ "A1"."COL1"
     , "A1"."COL2"
  FROM "REMOTE"."TABLE1" "A1"
 WHERE "A1"."COL1" =
   ANY ( SELECT "A2"."COL1"
       FROM "LOCAL"."TABLE1"@! "A2")

The issue is in the insert case the enitre table is being pulled across the dblink and then limited localy which takes a fair bit of time given the table size. Is there any reason adding the insert would change the behavior in this manner?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

塔塔猫 2024-09-01 15:57:58

您可能想要使用 Driving_site 提示。这里有一个很好的解释:
http://www.dba-oracle.com/t_sql_dblink_performance.htm

You may want to use the driving_site hint. There is a good explanation here:
http://www.dba-oracle.com/t_sql_dblink_performance.htm

带上头具痛哭 2024-09-01 15:57:58

当涉及到DML时,oracle选择忽略任何drive_site提示并在目标站点执行该语句。所以我怀疑你是否能够改变这一点(即使使用上述方法)。一种可能的解决方法是您可以在远程数据库上创建 LOCAL.TABLE1 的同义词,并在 INSERT 语句中使用相同的同义词。

When it comes to DML, oracle chooses to ignore any driving_site hint and executes the statement at the target site. So I doubt if you would be able to change that (even using WITH approach described above). A possible workaround is you can create a synonym for LOCAL.TABLE1 on the remote database and use the same in your INSERT statement.

情域 2024-09-01 15:57:58

利用WITH子句可以优化工作集的检索:

WITH remote_rows AS
     (SELECT /*+DRIVING_SITE(s)*/COL1, COL2
      FROM REMOTE.TABLE1@dblink s
      WHERE COL1 IN ( SELECT COL1 FROM WORKING_TABLE)) 
INSERT INTO LOCAL.TABLE_1 ( COL1, COL2)
SELECT  COL1, COL2
FROM remote_rows

Leveraging the WITH clause could optimize your retrieval of your working set:

WITH remote_rows AS
     (SELECT /*+DRIVING_SITE(s)*/COL1, COL2
      FROM REMOTE.TABLE1@dblink s
      WHERE COL1 IN ( SELECT COL1 FROM WORKING_TABLE)) 
INSERT INTO LOCAL.TABLE_1 ( COL1, COL2)
SELECT  COL1, COL2
FROM remote_rows
盛夏尉蓝 2024-09-01 15:57:58

Oracle 将忽略插入语句的 Driving_site 提示,因为 DML 始终在本地执行。执行此操作的方法是使用驱动站点提示创建一个游标,然后使用bulkcollect/forall循环游标并插入到目标本地表中。

Oracle will ignore the driving_site hint for insert statements, as DML is always executed locally. The way to do this is to create a cursor with the driving site hint, and then loop through the cursor with a bulkcollect/forall and insert into the target local table.

任谁 2024-09-01 15:57:58

WORKING_TABLE 有多大?
如果它足够小,您可以尝试从 work_table 中选择到一个集合中,然后将该集合的元素作为 IN 列表中的元素传递。

declare
  TYPE t_type IS TABLE OF VARCHAR2(60);
  v_coll t_type;
begin
  dbms_application_info.set_module('TEST','TEST');
  --
  select distinct object_type 
  bulk collect into v_coll
  from user_objects;
  --
  IF v_coll.count > 20 THEN
    raise_application_error(-20001,'You need '||v_coll.count||' elements in the IN list');
  ELSE
    v_coll.extend(20);
  END IF;
  insert into abc (object_type, object_name)
  select object_type, object_name
  from user_objects@tmfprd
  where object_type in 
            (v_coll(1), v_coll(2), v_coll(3), v_coll(4), v_coll(5), 
            v_coll(6), v_coll(7), v_coll(8), v_coll(9), v_coll(10),
            v_coll(11), v_coll(12), v_coll(13), v_coll(14), v_coll(15), 
            v_coll(16), v_coll(17), v_coll(18), v_coll(19), v_coll(20)
             );
  --
  dbms_output.put_line(sql%rowcount);
end;
/

How big is WORKING_TABLE ?
If it is small enough, you could try selecting from work_table into a collection, and then passing the elements of that collect as elements in an IN list.

declare
  TYPE t_type IS TABLE OF VARCHAR2(60);
  v_coll t_type;
begin
  dbms_application_info.set_module('TEST','TEST');
  --
  select distinct object_type 
  bulk collect into v_coll
  from user_objects;
  --
  IF v_coll.count > 20 THEN
    raise_application_error(-20001,'You need '||v_coll.count||' elements in the IN list');
  ELSE
    v_coll.extend(20);
  END IF;
  insert into abc (object_type, object_name)
  select object_type, object_name
  from user_objects@tmfprd
  where object_type in 
            (v_coll(1), v_coll(2), v_coll(3), v_coll(4), v_coll(5), 
            v_coll(6), v_coll(7), v_coll(8), v_coll(9), v_coll(10),
            v_coll(11), v_coll(12), v_coll(13), v_coll(14), v_coll(15), 
            v_coll(16), v_coll(17), v_coll(18), v_coll(19), v_coll(20)
             );
  --
  dbms_output.put_line(sql%rowcount);
end;
/
茶色山野 2024-09-01 15:57:58

插入 zith 基数提示似乎在 11.2 中有效

 INSERT /*+ append */  
        INTO MIG_CGD30_TEST       
                SELECT  /*+ cardinality(ZFD 400000) cardinality(CGD 60000000)*/ 
            TRIM (CGD.NUMCPT) AS NUMCPT, TRIM (ZFD.NUMBDC_NEW) AS NUMBDC
              FROM CGD30@DBL_MIG_THALER CGD,
                   ZFD10@DBL_MIG_THALER ZFD,
                   EVD01_ADS_DR3W2  EVD

Insert into zith cardinality hint seems to work in 11.2

 INSERT /*+ append */  
        INTO MIG_CGD30_TEST       
                SELECT  /*+ cardinality(ZFD 400000) cardinality(CGD 60000000)*/ 
            TRIM (CGD.NUMCPT) AS NUMCPT, TRIM (ZFD.NUMBDC_NEW) AS NUMBDC
              FROM CGD30@DBL_MIG_THALER CGD,
                   ZFD10@DBL_MIG_THALER ZFD,
                   EVD01_ADS_DR3W2  EVD
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文