关于ORACLE表缓存化的一些困惑 请教高手
ORACLE表缓存化的一些疑惑例:目前有表 A【数据量在10万以上】 和 表 B【数据量在100条以内】Oracle有缓存机制,如将某张表缓存化【alter table A cache;】
问题:
1. 这种方法在实际上大概有多少性能提升?
2. 如果仅将A表缓存化,会使用到如下语句:select a.id from A a, B b where a.userid = b.userid,是否有必要将B表也缓存化?;
3. 有一个说法:将特定表绑定内存,是否就是表缓存化?
这位朋友,你显然对oracle的工作机制极为不熟啊。
是否缓存一个表,轻易的不要去缓存,因为buffer cache的大小有限,oracle有优秀的机制(LRU)来去缓存表,手工缓存会影响buffer cache的使用,导致命中率下降。
可能这个表的性能提高了,但是整体呢?oracle的LRU很优秀(需要你去研究一下)。
一条sql语句的性能需要看它的执行计划,根据执行计划进行调整。 非常感谢,茅塞顿开 个人见解,这是一个明显的小表和大表的连接问题,只要索引建立得当并且统计信息也已经收集,那么这时ORACLE应该会使用nested loops进行连接查询,性能应该不差
SQL> create table bigtab(id number,name varchar2(32));
Table created.
SQL> create table smalltab(id number);
Table created.
--insert data to bigtab
declare
cnt number;
begin
for i in 1..1000000 loop
insert into bigtab values(i,sys_guid());
cnt := cnt + 1;
if mod(cnt,10000) = 0 and cnt >= 10000 then
commit;
end if;
end loop;
commit;
end;
/
SQL> select count(*) from bigtab;
COUNT(*)
----------
1000000
--insert data to smalltab
declare
n number := 0;
begin
for i in 1..200 loop
while (n=0) loop
n := floor(dbms_random.value*1000000);
end loop;
insert into smalltab values(n);
end loop;
commit;
end;
/
SQL> select count(*) from smalltab;
COUNT(*)
----------
200
SQL> create index idx_bigtab_id on bigtab(id);
Index created.
SQL> exec dbms_stats.gather_index_stats('SCOTT','IDX_BIGTAB_ID');
PL/SQL procedure successfully completed.
SQL> create index idx_smaltab_id on smalltab(id);
Index created.
SQL> exec dbms_stats.gather_index_stats('SCOTT','IDX_SMALTAB_ID');
PL/SQL procedure successfully completed.
explain plan for select t1.name from bigtab t1,smalltab t2 where t1.id = t2.id;
select * from table(dbms_xplan.display());
sen hash value: 3332719998
----------------------------------------------------------------------------------------------
| Id| Operation | Name | Rows| Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 200 |8800 | 402 (0)| 00:00:05 |
| 1 |TABLE ACCESS BY INDEX ROWID| BIGTAB | 1 | 31 | 3 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 200 |8800 | 402 (0)| 00:00:05 |
| 3 | INDEX FULL SCAN | IDX_SMALTAB_ID | 200 |2600 | 1 (0)| 00:00:01 |
|*4 | INDEX RANGE SCAN | IDX_BIGTAB_ID| 1 | | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------
lect * from table(dbms_xplan.display());
个人认为只有非常频繁的查询一张表并且表比较小时才需要把表keep到buffer_pool中,如在一个循环内部查询一张字典表,这时把这张字典表keep到内存后可以有效降低physical read,但是logical read还是避免不了的。 我们在优化一条SQL语句的时候,应该关心的是sql语句的logical read。
只有在sql语句每次物理读都很大的时候,我们才去关心这条sql语句的执行计划。 只有热点小表才需要。 好高深呀,能问个弱问题吗?physical read是什么呀?logical read又是什么呀?这两个之间有什么联系和区别吗? 好好的看看我发的视频,里面有逻辑读和物理读的详细的解释,Oracle一定需要系统的学习。 有学了一点儿!:)
页:
[1]