Sie müssen OUTER JOIN
nicht verwenden bis auf die Prüfung, wie viele Zeilen bzw. wird nicht gelöscht werden.
Ein Beispiel für eine solche Abfrage finden Sie unten (ich verwende generierte Testdaten, die am Ende der Antwort bereitgestellt werden)
with del as (
select delta.id, delta.version,
decode(big.id,null,0,1) is_deleted
from delta
left outer join big
on delta.id = big.id and delta.version = big.version
)
select is_deleted, count(*) cnt, max(id||'.'||version) eg_id_vers
from del
group by is_deleted;
IS_DELETED CNT EG_ID_VERS
---------- ---------- ----------
1 20000 99995.0
0 20 100100.0
Bei Ihrer Datengröße sollten Sie einen HASH JOIN
verwenden mit full table scan
auf beiden Tischen, um eine akzeptable Leistung zu erzielen.
Es gibt grundsätzlich zwei Möglichkeiten, wie man DELETE
durchführt
Aktualisierbare Beitrittsansicht
Beachten Sie, dass Ihre kleine Tabelle in diesem Fall einen eindeutigen Index haben muss ID, VERSION
(oder ein Primärschlüssel)
create unique index delta_idx on delta(id,version);
Im Gegensatz dazu sollte die BIG-Tabelle keine solche Einschränkung haben . Dies ist wichtig, da es deutlich anzeigt, dass Ihre BIG-Tabelle die einzige schlüsselerhaltende Tabelle ist in der Join-Ansicht.
Fügen Sie der kleinen Tabelle einfach einen Join hinzu Kann Zeilen nicht duplizieren vom großen Tisch aufgrund der einzigartigen Beschränkung
Siehe hier Weitere Informationen zum Aktualisieren von Beitrittsansichten
delete from
(
select delta.id, delta.version, big.id big_id, big.version
from big
join delta
on delta.id = big.id and delta.version = big.version
)
Das delete
oben entfernt Zeilen aus BIG
Tabelle, da dies die einzige schlüsselerhaltende Tabelle ist (siehe die Diskussion oben)
Diese DML führt zu einem HASH JOIN
Löschen mit EXISTS
Wenn Ihre kleine Tabelle keinen Primärschlüssel hat (d. h. sie kann doppelte Zeilen mit derselben ID and VERSION
enthalten ) müssen Sie zurückgreifen zu der in andere Antwort
vorgeschlagenen Lösung .
DELETE FROM big
WHERE EXISTS (SELECT null
FROM delta
WHERE delta.id = big.id and delta.version = big.version
)
Es sind keine Indizes erforderlich und Sie sollten einen Ausführungsplan mit HASH JOIN RIGHT SEMI
erwarten , was bedeutet, dass sich beide Ansätze nicht wirklich unterscheiden.
Beispieldaten für Test
create table big as
select
trunc(rownum/10) id, mod(rownum,10) version,
lpad('x',10,'Y') pad
from dual connect by level <= 1000000;
/* the DELTA table has 50 times less rows,
allow some rows out of range of the BIG table - those rows will not be deleted **/
drop table delta;
create table delta as
select
trunc(rownum*50/10) id, mod(rownum*50,10) version
from dual connect by level <= 1001000/50;
create unique index delta_idx on delta(id,version);