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

Sql 如何将重复查询的结果存储在Oracle的内存中?,sql,oracle,performance,caching,Sql,Oracle,Performance,Caching,为了准备一个数据库模式迁移,在这个迁移中我添加了大量带有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 paren

为了准备一个数据库模式迁移,在这个迁移中我添加了大量带有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)
(是的,有50个这样的表。)
parent
是一个具有足够记录的表,不需要对其多次运行id查询;我宁愿运行它一次,存储结果,并对照存储的查询结果检查子表的值

我找到了关于“临时表”的文档,这听起来像是我想要的。在MySQL中,我相信我可以指定
engine=memory
作为
createtable
语句的一个选项,以防止表存储在磁盘上。我在甲骨文中看不到做同样事情的方法


我的内存缓存选项是什么?
select id from parent
查询的结果?

Oracle使用多种类型的缓存,您可能不需要执行任何操作即可自动缓存
parent.id

缓冲区缓存是最大也是最重要的缓存,它包含数据块(通常为8KB)。缓冲区缓存可以包含来自表或索引的块。由于Oracle能够直接从索引中读取数据,而无需使用该表,因此它只能缓存
ID
值的索引块,这些值应该可以很好地存储在内存中

下面的测试用例显示了一个简单的父/子表,Oracle将100%的索引缓存在
ID
上,50个查询中有49个完全从内存读取

创建父/子表,添加10万个样本行,收集优化器统计数据以获得最佳执行计划。

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;
/
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")
--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';
运行一次查询

select * from child where parent_id not in (select id from parent);
索引的每个块都被缓存。下一次运行将从内存中读取数据。

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;
/
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")
--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';

有很多方法可以将结果存储在内存中,比如使用结果缓存。但对于您描述的问题,您可能不需要做任何事情来实现近乎完美的缓存。

Oracle使用多种类型的缓存,您可能不需要做任何事情来自动缓存
PARENT.ID

缓冲区缓存是最大也是最重要的缓存,它包含数据块(通常为8KB)。缓冲区缓存可以包含来自表或索引的块。由于Oracle能够直接从索引中读取数据,而无需使用该表,因此它只能缓存
ID
值的索引块,这些值应该可以很好地存储在内存中

下面的测试用例显示了一个简单的父/子表,Oracle将100%的索引缓存在
ID
上,50个查询中有49个完全从内存读取

创建父/子表,添加10万个样本行,收集优化器统计数据以获得最佳执行计划。

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;
/
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")
--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';
运行一次查询

select * from child where parent_id not in (select id from parent);
索引的每个块都被缓存。下一次运行将从内存中读取数据。

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;
/
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")
--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';
有很多方法可以将结果存储在内存中,比如使用结果缓存。但对于您描述的问题,您可能不需要做任何事情来实现近乎完美的缓存