我有两个表tableA(33M记录)和tableB(270K记录), 我想删除tableA中也存在于tableB中的所有记录。所以在下面写一个SQL语句。 我认为它应该被修改,因为它超过1小时表将它们全部删除。 你是否知道这种操作是否正常。 注意:两个表的主键都是id。
delete from tableA where id in (select id from tableB);
这是sql语句解释
| 0 | DELETE STATEMENT | | 289K| 7341K| | 85624 (1)| 00:17:08 |
| 1 | DELETE | tableA | | | | | |
| 2 | MERGE JOIN | | 289K| 7341K| | 85624 (1)| 00:17:08 |
| 3 | INDEX FULL SCAN | SYS_C0015397 | 36M| 455M| | 84050 (1)| 00:16:49 |
|* 4 | SORT JOIN | | 289K| 3670K| 11M| 1574 (1)| 00:00:19 |
| 5 | INDEX FAST FULL SCAN| SYS_C0015401 | 289K| 3670K| | 193 (2)| 00:00:03 |
---------------------------------------------------------------------------------------------------
答案 0 :(得分:1)
这是一个有趣的执行计划。您通常不会看到合并连接,因为它们通常首先需要一种数据,但在这种情况下,只需要对一个数据集进行排序,因为它是通过索引快速全扫描(返回未排序的数据)而不是索引来访问的全扫描。
大部分成本与通过索引全扫描读取SYS_C0015397索引相关联,我猜测优化器已完成一对快速完全扫描和散列连接的算法并拒绝它。不过,我会看看是否可以暗示:
delete /*+ no_use_merge(tablea) */ from ...
我不确定这是否足以获得散列连接,但看看解释计划是否尝试了除合并连接之外的其他内容。
tablea上的join列是唯一的还是PK?
答案 1 :(得分:0)
使用exists或将保存的数据插入新表(B),删除旧表(A)并将新表(B)重命名为表(A)。