Você não precisa usar
OUTER JOIN
exceto para verificar quantas linhas serão resp. não ser excluído. Um exemplo de tal consulta veja abaixo (eu uso dados de teste gerados fornecidos no final da resposta)
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
Com o tamanho dos seus dados, você deve usar um
HASH JOIN
com full table scan
em ambas as tabelas para obter um desempenho aceitável. Existem basicamente duas opções de como fazer o
DELETE
Visualização de associação atualizável
Observe que, neste caso, sua pequena tabela deve ter um índice exclusivo em
ID, VERSION
(ou uma chave primária) create unique index delta_idx on delta(id,version);
Ao contrário, a tabela BIG não deve ter essa restrição . Isso é importante porque indica claramente que sua tabela BIG é a única tabela preservadora de chaves na visualização de junção.
Simples, coloque uma junção na pequena tabela não pode duplicar linhas da mesa grande devido à restrição única
Consulte aqui mais informações sobre Atualização de visualizações de junção
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
)
O
delete
acima remove linhas do BIG
table porque esta é a única tabela preservadora de chaves (veja a discussão acima) Este DML leva a um
HASH JOIN
Excluir com EXISTS
Se sua pequena tabela não tiver chave primária (ou seja, pode conter linhas duplicadas com o mesmo
ID and VERSION
) você deve substituir para a solução proposta em outra resposta
. DELETE FROM big
WHERE EXISTS (SELECT null
FROM delta
WHERE delta.id = big.id and delta.version = big.version
)
Nenhum índice é necessário e você deve esperar um plano de execução com
HASH JOIN RIGHT SEMI
, o que significa que ambas as abordagens não são realmente diferentes. Dados de amostra para teste
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);