OUTER JOIN
を使用する必要はありません 応答する行数のチェックを除いて。 しない 削除されます。
このようなクエリの例を以下に示します(回答の最後に提供されている生成されたテストデータを使用します)
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
データサイズでは、HASH JOIN
を使用する必要があります full table scan
を使用 許容できるパフォーマンスを得るために両方のテーブルで。
DELETE
の実行方法には基本的に2つのオプションがあります
更新可能な参加ビュー
この場合、小さなテーブルには一意のインデックスが必要です。 ID, VERSION
(または主キー)
create unique index delta_idx on delta(id,version);
反対に、BIGテーブルにはそのような制約があってはなりません 。これは重要です。これは、BIGテーブルが唯一のキー保存テーブルであることを明確に示しているためです。 結合ビューで。
単純に小さなテーブルに結合を配置します行を複製できません 独自の制約による大きなテーブルから
こちら 結合ビューの更新の詳細
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
上記はBIG
から行を削除します これが唯一のキー保存テーブルであるため、テーブル (上記の説明を参照)
このDMLはHASH JOIN
につながります
EXISTSで削除
小さなテーブルに主キーがない場合(つまり、同じID and VERSION
を持つ重複した行が含まれている可能性がある場合 )フォールバックする必要があります その他の回答
で提案されたソリューションへ 。
DELETE FROM big
WHERE EXISTS (SELECT null
FROM delta
WHERE delta.id = big.id and delta.version = big.version
)
インデックスは必要ありません。HASH JOIN RIGHT SEMI
を使用した実行プランを期待する必要があります。 、つまり、両方のアプローチに実際の違いはありません。
テスト用のサンプルデータ
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);