oracle123 发表于 2010-11-3 11:48:31

关于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. 有一个说法:将特定表绑定内存,是否就是表缓存化?

oraunix 发表于 2010-11-3 13:05:10

这位朋友,你显然对oracle的工作机制极为不熟啊。
是否缓存一个表,轻易的不要去缓存,因为buffer cache的大小有限,oracle有优秀的机制(LRU)来去缓存表,手工缓存会影响buffer cache的使用,导致命中率下降。
可能这个表的性能提高了,但是整体呢?oracle的LRU很优秀(需要你去研究一下)。
一条sql语句的性能需要看它的执行计划,根据执行计划进行调整。

oracle123 发表于 2010-11-3 13:55:28

非常感谢,茅塞顿开

chenyu 发表于 2010-11-3 17:45:46

个人见解,这是一个明显的小表和大表的连接问题,只要索引建立得当并且统计信息也已经收集,那么这时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还是避免不了的。

oraunix 发表于 2010-11-8 17:35:40

我们在优化一条SQL语句的时候,应该关心的是sql语句的logical read。
只有在sql语句每次物理读都很大的时候,我们才去关心这条sql语句的执行计划。

北极光 发表于 2012-5-17 13:10:06

只有热点小表才需要。

石沉┏溪洞 发表于 2012-5-18 23:54:39

好高深呀,能问个弱问题吗?physical read是什么呀?logical read又是什么呀?这两个之间有什么联系和区别吗?

oraunix 发表于 2012-5-20 09:31:53

好好的看看我发的视频,里面有逻辑读和物理读的详细的解释,Oracle一定需要系统的学习。

经纪人 发表于 2012-5-30 09:47:53

有学了一点儿!:)
页: [1]
查看完整版本: 关于ORACLE表缓存化的一些困惑 请教高手