2010-03-17 11 views
7

Ich bin 10 über eine dblink in Oracle ein wenig Mühe mit einem Auswahl in Einsatz ich die folgende Anweisung verwenden:Auswählen und Setzen über dblink

INSERT INTO LOCAL.TABLE_1 (COL1, COL2) 
SELECT COL1, COL2 
FROM [email protected] s 
WHERE COL1 IN (SELECT COL1 FROM WORKING_TABLE) 

Wenn ich die Anweisung ausführen folgende ist, was wird gegen den Remote-Server auf dem DB-Link zu laufen:

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

Wenn ich laufen die Auswahl nur und nicht tun, um den Einsatz in den folgenden ausgeführt wird:

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

Das Problem ist im Einfügefall die Entire-Tabelle wird über den dblink gezogen und dann begrenzt localy, die angesichts der Tabellengröße ein wenig Zeit braucht. Gibt es einen Grund, den Einsatz hinzuzufügen, würde das Verhalten auf diese Weise ändern?

Antwort

3

Sie können den Hinweis driving_site verwenden. Es gibt eine gute Erklärung hier: http://www.dba-oracle.com/t_sql_dblink_performance.htm

+0

Ich hatte versucht, vor der Buchung den folgenden Hinweis zur ersten Abfrage hinzuzufügen, aber die gleichen Ergebnisse erhalten. /* + DRIVING_SITE (s) */ Das wäre Hinweise auf die dblink Seite richtig fahren? – Domtar

2

die WITH-Klausel Nutzung könnte Ihr Abruf Ihrer optimieren Workingset:

WITH remote_rows AS 
    (SELECT /*+DRIVING_SITE(s)*/COL1, COL2 
     FROM [email protected] s 
     WHERE COL1 IN (SELECT COL1 FROM WORKING_TABLE)) 
INSERT INTO LOCAL.TABLE_1 (COL1, COL2) 
SELECT COL1, COL2 
FROM remote_rows 
+0

[Diese Antwort] (http://stackoverflow.com/questions/5885154/oracle-sql-insert-into-with-with-clause#5885845) zeigt, dass Ihre Syntax hier nicht korrekt ist. – Alfabravo

3

Wenn es um DML kommt, Orakel jede driving_site Hinweis zu ignorieren wählt und führt die Anweisung an der Zielseite. Ich bezweifle also, dass Sie das ändern könnten (sogar mit dem oben beschriebenen WITH-Ansatz). Eine mögliche Problemumgehung besteht darin, dass Sie in der entfernten Datenbank ein Synonym für LOCAL.TABLE1 erstellen und dasselbe in Ihrer INSERT-Anweisung verwenden können.

0

Wie groß ist WORKING_TABLE? Wenn es klein genug ist, könnten Sie versuchen, aus work_table eine Sammlung auszuwählen und dann die Elemente dieser Sammlung als Elemente in einer IN-Liste zu übergeben.

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 [email protected] 
    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; 
/
+0

Das war meine erste Annäherung, aber es könnte mehr als 1000 Elemente in der Arbeitstisch sein. Ich denke, dass ich die Verarbeitung von Gruppen von 1000 brechen muss, um mit dem wo in Grenzen zu bleiben. – Domtar

+0

Können Sie eine globale temporäre Tabelle auf der Remote-Seite des Links erstellen? Sie könnten dies von der Arbeitstabelle einfügen, dann wäre die Verbindung allesamt auf der entfernten Seite. –

0

Insert in ZITH Mächtigkeit Hinweis scheint 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 [email protected]_MIG_THALER CGD, 
        [email protected]_MIG_THALER ZFD, 
        EVD01_ADS_DR3W2 EVD 
1

Oracle ignoriert den driving_site Hinweis für Insert-Anweisungen zu arbeiten, da DML immer lokal ausgeführt wird. Die Methode besteht darin, einen Cursor mit dem Hinweis für den treibenden Standort zu erstellen und anschließend mit dem Befehl bulkcollect/forall den Cursor zu durchlaufen und in die lokale Zieltabelle einzufügen.