2023年3月

提问,如果把表keep到内存后,读取大表的时候, 还会触发直接路径读吗?

线上问题
一、原服务器内存24G、oracle设置内存为18G、目前服务器扩容到64G

二、部分热点表数据行已上百万、读取过于频繁、考虑KEEP到内存中

解决方案
一、内存调整
注:

1、正常设置为物理内存的75% 、线上设置成48G

2、sga_target不能大于sga_max_size,可以设置为相等

3、SGA加上PGA等其他进程占用的内存总数必须小于操作系统的物理内存

4、修改完成后重启数据库生效

--显示内存分配情况
show parameter sga;
--修改占用内存的大小
alter system set sga_max_size=48000m scope=spfile;
--修改SGA的大小:
alter system set sga_target=48000m scope=spfile;

二、设置表KEEP内存
注:

1、设置后及时生效、线上设置了10G空间的缓存、查询了实际需要KEEP的表、实际占用空间为5G、设置10G够用几年

--查看KEEP缓存空间
show parameter db_keep_cache_size
--设置KEEP缓存空间
alter system set db_keep_cache_size=10000M scope=both;

三、添加表到KEEP中
注:

1、设置后及时生效

2、想要看具体详细数据、可以直接查询dba_segments表

--将表缓存到内存中
alter table t_cdeli_wait_processing_info storage(buffer_pool keep);
--取消表缓存
alter table t_cdeli_wait_processing_info storage(buffer_pool default);
--查询总大小
select component,current_size from v$sga_dynamic_components where component='KEEP buffer cache';
--查询已缓存表
select segment_name from dba_segments where BUFFER_POOL = 'KEEP';
————————————————
版权声明:本文为CSDN博主「wucao110」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wucao110/article/details/125271195

Plan hash value: 2490995645
 
-------------------------------------------------------------------------------------------
| Id  | Operation           | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                     |       |       |   465K(100)|          |
|   1 |  SORT AGGREGATE     |                     |     1 |    38 |            |          |
|   2 |   NESTED LOOPS OUTER|                     | 51621 |  1915K|   465K  (1)| 01:33:05 |
|*  3 |    TABLE ACCESS FULL| BYDD9WMS_PRINT_DATA | 51621 |  1058K|   465K  (1)| 01:33:02 |
|*  4 |    INDEX UNIQUE SCAN| UK_PO_DATA          |     1 |    17 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - filter(("AA"."CODE_DATE" IS NULL AND "AA"."DATECODE" IS NOT NULL AND 
              NVL("AA"."UPDATE_NAME",'X')<>'UPCD2303210001'))
   4 - access("PD"."PO"="AA"."PO" AND "PD"."LINE"="AA"."LINE")
 
Note
-----
   - cardinality feedback used for this statement

查看执行计划发现:cardinality feedback used for this statement
11g之后的新特性, 如果cbo发现e_row和a_row的差距过多, 认为执行计划不准确,则重新生成执行计划。
检查发现对应的表的统计信息,上次分析是3年前,说明上次导入之后,连带统计信息也被导入,到目前为止,更新的次数不超过原来的10%,所以一直未更新。
所以可以在业务空闲时间重新收集统计信息,但是目前等待事件为全表扫描的io,cpu资源空闲较多,所以重新收集统计信息也无用,需要sql优化,减少全表扫描次数。才会有明显改善,检查业务逻辑发现,该动作是对一张800万的表进行全表扫描,可以预见,未来随着业务的增长,该语句的性能会越来越低,最终将无法执行下去,可能的措施是归档历史数据,或者改变表结构为分区表。减少查询扫描的范围。

declare   
    ---define Cursor 
    cur_policy_sql  VARCHAR2(32767) := 'select * from  (select object_id,object_name 
     from t1111 order by object_id )  
     where rownum < 10' ;
    Cursor cur_policy is  
     select * from  (select object_id,object_name 
     from t1111 order by object_id )  
     where rownum < 10 ;  
    curPolicyInfo cur_policy%rowtype;---定义游标变量  
Begin  
   Dbms_Output.put_line(cur_policy_sql);
   open cur_policy; ---open cursor  
   Loop   
     --deal with extraction data from DB  
     Fetch cur_policy into curPolicyInfo;  
     Exit when cur_policy%notfound;  
        
     Dbms_Output.put_line(curPolicyInfo.object_id); 
     Dbms_Output.put_line(cur_policy%ROWCOUNT); 
   end loop;  
   
   Exception   
     when others then  
         close cur_policy;  
         Dbms_Output.put_line(Sqlerrm);  
           
   if cur_policy%isopen then    
    --close cursor   
      close cur_policy;  
   end if;  
end;