Bạn không cần sử dụng OUTER JOIN
ngoại trừ việc kiểm tra bao nhiêu hàng sẽ tương ứng. sẽ không bị xóa.
Ví dụ về truy vấn như vậy xem bên dưới (Tôi sử dụng dữ liệu thử nghiệm đã tạo được cung cấp ở cuối câu trả lời)
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
Với kích thước dữ liệu của mình, bạn nên sử dụng HASH JOIN
với full table scan
trên cả hai bảng để có được hiệu suất có thể chấp nhận được.
Về cơ bản có hai tùy chọn để thực hiện DELETE
Chế độ xem tham gia có thể cập nhật
Lưu ý rằng trong trường hợp này, bảng nhỏ của bạn phải có một chỉ mục duy nhất trên ID, VERSION
(hoặc khóa chính)
create unique index delta_idx on delta(id,version);
Trái ngược với bảng LỚN nên không có ràng buộc như vậy . Điều này rất quan trọng vì nó chỉ ra rõ ràng rằng bảng LỚN của bạn là một bảng bảo quản khóa duy nhất trong chế độ xem tham gia.
Đơn giản, hãy đặt một phép nối vào bảng nhỏ không thể trùng lặp các hàng khỏi bàn lớn do sự tương phản độc đáo
Xem tại đây thêm thông tin về Cập nhật chế độ xem tham gia
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
ở trên xóa các hàng khỏi BIG
bảng vì đây là bảng bảo quản khóa duy nhất (xem thảo luận ở trên)
DML này dẫn đến một HASH JOIN
Xóa bằng EXISTS
Nếu bảng nhỏ của bạn không có khóa chính (tức là bảng có thể chứa các hàng trùng lặp có cùng ID and VERSION
) bạn phải dự phòng giải pháp được đề xuất trong câu trả lời khác
.
DELETE FROM big
WHERE EXISTS (SELECT null
FROM delta
WHERE delta.id = big.id and delta.version = big.version
)
Không cần lập chỉ mục và bạn sẽ có kế hoạch thực thi với HASH JOIN RIGHT SEMI
, có nghĩa là cả hai cách tiếp cận không thực sự khác nhau.
Dữ liệu mẫu để kiểm tra
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);