Nie musisz używać OUTER JOIN
z wyjątkiem sprawdzenia ile rzędów będzie ew. nie zostać usunięte.
Przykład takiego zapytania patrz poniżej (używam wygenerowanych danych testowych podanych na końcu odpowiedzi)
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
Ze swoim rozmiarem danych powinieneś użyć HASH JOIN
z full table scan
na obu stołach, aby uzyskać akceptowalną wydajność.
Istnieją zasadniczo dwie opcje, jak wykonać DELETE
Aktualny widok dołączania
Pamiętaj, że w tym przypadku Twój mały stolik musi mieć unikalny indeks na ID, VERSION
(lub klucz podstawowy)
create unique index delta_idx on delta(id,version);
W przeciwieństwie do tabeli BIG nie powinna mieć takiego ograniczenia . Jest to ważne, ponieważ wyraźnie wskazuje, że DUŻA tabela jest jedyną tablicą zachowującą klucze w widoku łączenia.
Po prostu umieść sprzężenie w małym stole nie można powielać wierszy z dużego stołu ze względu na unikalne ograniczenie
Zobacz tutaj więcej informacji o aktualizowaniu widoków przyłączenia
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
)
delete
powyżej usuwa wiersze z BIG
tabeli, ponieważ jest to jedyna tabela zachowująca klucze (patrz dyskusja powyżej)
Ten DML prowadzi do HASH JOIN
Usuń za pomocą EXISTS
Jeśli Twoja mała tabela nie ma klucza podstawowego (tzn. może zawierać zduplikowane wiersze o tym samym ID and VERSION
) musisz zastąpić do rozwiązania zaproponowanego w innej odpowiedzi
.
DELETE FROM big
WHERE EXISTS (SELECT null
FROM delta
WHERE delta.id = big.id and delta.version = big.version
)
Żadne indeksy nie są wymagane i należy oczekiwać planu wykonania z HASH JOIN RIGHT SEMI
, co oznacza, że oba podejścia nie różnią się tak naprawdę.
Przykładowe dane do testu
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);