为了准备数据库架构迁移,在其中我通过ON CASCADE DELETE添加了很多外键约束,我需要运行清除孤立行的数据迁移。该数据迁移目前看起来像这样
delete from child1 where parent_id not in (select id from parent)
delete from child2 where parent_id not in (select id from parent)
...
delete from child50 where parent_id not in (select id from parent)
(是,有五十个这样的表。)parent
是一个具有足够记录的表,希望不必对它多次运行id查询;我宁愿运行一次,存储结果,并对照存储的查询结果检查子表的值。
我已经找到了有关“临时表”的文档,这听起来像我想要的东西。我相信在MySQL中,我可以指定engine=memory
作为CREATE TABLE
语句的选项,以防止将该表存储在磁盘上。我看不到在Oracle中执行相同操作的方法。
用于将select id from parent
查询的结果缓存到内存中的选项有哪些?
Oracle使用多种类型的缓存,对于自动缓存PARENT.ID
,您可能不需要执行任何操作。
缓冲区高速缓存是最大,最重要的高速缓存,它包含数据块(通常为8KB)。缓冲区高速缓存可以包含来自表或索引的块。由于Oracle能够直接从索引读取而不使用表,因此它只能缓存ID
值的索引块,该值应该很好地适合于内存。
[下面的测试用例显示了一个简单的父/子表,其中Oracle在ID
上缓存了100%的索引,而50个查询中的49个将完全从内存中读取。
创建父/子表,添加100K样本行,收集优化器统计信息以获取最佳执行计划。
create table parent(id number, a varchar2(100), b varchar2(100),
constraint parent_pk primary key(id));
insert into parent select level, 'aaaaaaaaaa', 'bbbbbbbbbb' from dual connect by level <= 100000;
create table child(id number primary key, parent_id number,
constraint child_fk foreign key (parent_id) references parent(id));
insert into child select level, level from dual connect by level <= 100000;
commit;
begin
dbms_stats.gather_table_stats(user, 'PARENT');
dbms_stats.gather_table_stats(user, 'CHILD');
end;
/
执行计划具有INDEX FAST FULL SCAN,在该计划中,它使用类似于瘦表的索引。
explain plan for
select * from child where parent_id not in (select id from parent);
select * from table(dbms_xplan.display);
Plan hash value: 3673552324
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 15000 | 125 (4)| 00:00:01 |
|* 1 | HASH JOIN RIGHT ANTI SNA| | 1000 | 15000 | 125 (4)| 00:00:01 |
| 2 | INDEX FAST FULL SCAN | PARENT_PK | 100K| 488K| 53 (2)| 00:00:01 |
| 3 | TABLE ACCESS FULL | CHILD | 100K| 976K| 70 (3)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("PARENT_ID"="ID")
运行一次查询
select * from child where parent_id not in (select id from parent);
索引的每个块都被缓存。下次运行将从内存中读取数据。
--Number of cached blocks for PARENT_PK: 256
select count(distinct block#)
from v$bh
where objd = (select object_id from dba_objects where object_name = 'PARENT_PK')
order by class#;
--Total number of blocks for PARENT_PK: 256
select blocks
from dba_segments
where segment_name = 'PARENT_PK';
有are种方法将结果存储在内存中,就像结果缓存一样。但是对于您描述的问题,您可能不需要执行任何操作即可获得近乎完美的缓存。