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

写了 4 篇文章,拥有财富 12,被 1 人关注

转播转播 分享分享 分享淘帖
回复

使用道具

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

使用道具

P3 | 发表于 2010-11-3 13:55:28
非常感谢,茅塞顿开
回复

使用道具

P4 | 发表于 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还是避免不了的。

评分

参与人数 1金币 +4 收起 理由
oraunix + 4

查看全部评分

回复

使用道具

P6 | 发表于 2010-11-8 17:35:40
我们在优化一条SQL语句的时候,应该关心的是sql语句的logical read。
只有在sql语句每次物理读都很大的时候,我们才去关心这条sql语句的执行计划。
回复

使用道具

P3 | 发表于 2012-5-17 13:10:06
只有热点小表才需要。
回复

使用道具

P4 | 发表于 2012-5-18 23:54:39
好高深呀,能问个弱问题吗?physical read是什么呀?logical read又是什么呀?这两个之间有什么联系和区别吗?
回复

使用道具

P6 | 发表于 2012-5-20 09:31:53
好好的看看我发的视频,里面有逻辑读和物理读的详细的解释,Oracle一定需要系统的学习。
回复

使用道具

P4 | 发表于 2012-5-30 09:47:53
有学了一点儿!
回复

使用道具

您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

意见
反馈