这是在做一份某客户的数据库性能检查报告时发现的问题:
top5等待事件中,
direct
path
read的等待占据第一位,占db time 的60%,是严重的等待。后来通过ASH报告看到进行低效的sql执行时进行的是全表扫描,产生了大量的
direct
path
read等待,在oracle 10g及以前的版本,全表扫描产生的应该是db file scattered
read等待,而在11g中,是不是有不同的特性呢?通过查看资料,我有以下的总结(部分内容经过测试如10949的事件设置):
在11g以前,进行全表扫描,产生的是数据块的多块读,以db file scattered reads等待事件体现,而在11g中,oracle使用了一种新的特性,当进行全表扫描的时候,数据库会直接从数据文件中读数据块,产生
direct
path reads等待,使用这种数据读取方式的判断依据是根据表的大小,以及当前数据库设置的buffer cache大小。当buffer cache 过小,而需要缓存的表为大表时,数据库会选择绕过buffer cache,直接将数据块读入PGA中,这样就避免每次执行SQL时因为表缺少索引而使用全表扫描,引致buffer cache因缓存表数据而重新刷新。
里面涉及到许多隐含参数--"_small_table_threshold",它的值衡量了大表和小表的界限。超过这个阀值的被认为是大表。当全表扫描的是小表时并不会使用直接路径读。
另一个隐含参数就是"_very_large_object_threshold" ,它定义了使用直接读进行全表扫描的表对象的最大值(MB)。如果只是单独设置这个参数对全秒扫描时选择数据读取方式的选择并不起作用。
执行
direct
path
read的好处有:当sql进行全表扫描时,如果仍然使用离散读的方式,则进程需要将存储中相连的数据块读入buffer cache,而这些连续的数据块中如果已经有部分不连续的块被缓存到cache中,数据库实际上进行的是对存储中剩下的数据块进行一个一个的顺序读,这样执行效率大大降低,因此选择直接读来一次性完成全表扫描需要读取的数据。另外,正因为不用将数据块读入buffer,减少了Cache Buffer Chain 和Cache Buffer LRU Chain 栓锁竞争,大大降低CPU的使用时间。
但是使用
direct
path
read同样有缺点:每次执行全表扫描的时候跳过buffer cache,将数据直接从存储读到用户PGA中,产生比较大的物理IO,造成磁盘IO压力。另外,在直接读取某段数据前可能需对该对象进行一次段级检查点,以防止读入的是旧的数据块。
关于手工禁止直接路径读:
设置10949事件可以令到数据库不使用
direct
path
read的方式进行大表的全表扫描。但是这个事件只在表的大小小于5倍的buffer cache时产生作用。因此,结合10949事件,确保隐含参数"_very_large_object_threshold",使该参数值小于被扫描的表对象的0.8倍大小,即可禁止
direct
path
read进行全表扫描。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24582392/viewspace-704305/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/24582392/viewspace-704305/