oracle关闭直接路径读,Oracle 直接路径读取等待事件

2024年 2月 6日 67.4k 0

直接路径读取等待事件

这个事件DPR在10G是没有的,是11G新等待事件,目的是让全表扫描和快速索引扫描不走SGA,直接从数据文件读到PGA

direct path read的优势

1、采用直接路径读取后,总能保证读取的块数是多块读参数设置的大小,提高了读取的效率

2、大大的降低了对于latch的使用,进而避免了可能导致的latch竞争(cbc latch等)

3、降低了全表扫描对buffer cache的冲击

4、降低了buffer pin的开销,有可能降低buffer busy waits等相关等待

direct path read可能的副作用

1、会发生段一级的检查点(后面详细介绍),因此在查询真正开始执行前,会做这个额外的准备工作。而且可能会造成IO抖动,因为要写脏数据。

2、如果你的表需要频繁的全表扫描读取,还是用传统的读取方式比较好。

3、在MOS中搜索direct path read,会发现它可能会导致多次的延迟块清除

direct path read较高的可能原因有:

1. 大量的磁盘排序操作,order by, group by, union, distinct, rollup, 无法在PGA中完成排序,需要利用temp表空间进行排序。

当从临时表空间中读取排序结果时,会产生direct path read.

2. 大量的Hash Join操作,利用temp表空间保存hash区。

3. SQL语句的并行处理

4. 大表的全表扫描,

5。全索引扫描。

在实际应用情况下尤其是OLTP还有混合类型的数据库,没有做到真正的读写分离架构的传统设计模式的C/S数据库。

那些SQL语句执行频繁又大量的全表扫描,全索引扫描。由于没有SGA的缓存,每一次查询都需要从存储读取产生了大量的物理读,最终导致I/O 100%。

由于处理速度慢,CPU又产生了大量的等待队列,所以DB Time也非常高。

另外 大量的表直接路径读会导致段的检查点的触发,把脏块回写到磁盘,如果该表读写也比较频繁的话,那么LGWR写得也多了起来,同时引起控制文件写操作。

在本来繁忙的IO时间里加上日志写,简直雪上加霜了。

直接路径读取等待事件 涉及多个隐含参数和1个事件

第一个隐含参数:

_serial_direct_read = false 禁用direct path read

_serial_direct_read = true 启用direct path read

alter sytem set "_serial_direct_read"=never scope=both sid='*';

可以显着减少direct path read

这个参数类似于总开关,可惜在11.2.0.4下不生效。

第二个隐含参数:

_small_table_threshold

单位是block, 表小于该块的数量,一定不走直接路径。

第三个隐含参数:

_very_large_object_threshold

当该表大于此倍数是,一定走直接路径。 我这里11.2.0.4 默认值是500 单位不是MB 记住不是MB

那到底是多少大小才呢? 这涉及第3个参数

第四个隐含参数:

_db_block_buffers

意思是:Number of database blocks cached in memory: hidden parameter

我这里11.2.0.4 值是 1336660 约等于10GB 低于我的BUFFER CACHE 32GB。

公式:_very_large_object_threshold/100*_db_block_buffers

那么第三个应该是 5倍 第4个参数大小,我这里应该是50GB 就必须走直接路径读取。

第五个隐含参数:

__direct_read_decision_statistics_driven

When this parameter is FALSE, the direct path read decision is done based on the segment header’s block count (actual block count).

When TRUE (default in 11.2.0.2+), the direct path read decision is done based on the block count stored in one of the base tables (TAB$, IND$) – the optimizer statistics

意思是说 表的块值是从哪里获取,从统计信息表还是段头呢?

只所以把它拿出来说,因为很多时候统计信息和真实信息不一致,也会导致不必要的直接路径读取。

那么像我这里大于208MB 小于50GB 该怎么办呢?

这就要看另外两个条件了

第一个阀值:脏块阀值,由于direct path read需要出发一个段的检查点,因此脏块太多,刷新脏块可能会导致IO繁忙

第二个阀值:表在内存里的cache率,如果cache率很高,那么还是走传统路径更快

最后一个事件是来关闭

alter system set event= ’10949 trace name context forever, level 1′ scope=spfile;

重启数据库

也可在会话中

alter session set events '10949 trace name context forever, level 1';

不过这个事件依旧不是强有效果的。它尽量地关闭介于208MB到50GB的表不走直接路径。

这个超级性能BUG 在12.1.0.2 引入自动大表缓存,将BUFFER CACHE 划出部分为大表缓存区

并且统计表和索引的热度,将其放到CACHE 避免频繁DIRECT PATH READ。

ALTER DATABASE NO FORCE FULL DATABASE CACHING;

alter system set db_big_table_cache_percent_target = 90;

视图:

V$Bt_scan_cache;v$Bt_scan_obj_temps

对于使用很广的11.2.0.4朋友来说该怎么办呢?

方法一:关闭它

alter system set event= ’10949 trace name context forever, level 1′ scope=spfile;

alter system set "_serial_direct_read"=false scope=spfile;

方法二:调高下限

alter system set "_small_table_threshold"=262144 scope=spfile; 约2G

方法三:避免统计信息错误

alter system set "__direct_read_decision_statistics_driven"=FALSE scope=spfile;

方法四: KEEP CACHE

ALTER TABLE T STORAGE (BUFFER_POOL KEEP)

我们人工的把一些大表KEEP进BUFFER CACHE,这样类似于12C的大表缓存特效了

alter system set db_keep_cache_size=2G scope=spfile;

KEEP池其实是一块可用内存采用类似循环的算法进行访问。

如果KEEP池里面还有剩余空间,则新的数据会首先使用剩余的空间,如果KEEP池已经存储满了,Oracle会从头开始重用KEEP池。

方法五 对全表尽可能建索引。

建索引比优化SQL来的快!

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论