如何将重复查询的结果存储在Oracle的内存中?

问题描述 投票:1回答:1

为了准备数据库架构迁移,在其中我通过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查询的结果缓存到内存中的选项有哪些?

sql oracle performance caching
1个回答
0
投票

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种方法将结果存储在内存中,就像结果缓存一样。但是对于您描述的问题,您可能不需要执行任何操作即可获得近乎完美的缓存。


推荐问答