oracle 11G direct path read 很美也很伤人,oracle11g
direct path read
在11g中,全表扫描可能使用direct path read方式,绕过buffer cache,这样的全表扫描就是物理读了。
在10g中,都是通过gc buffer来读的,所以不存在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. 大表的全表扫描,在中,全表扫描的算法有新的变化,根据表的大小、高速缓存的大小等信息,决定是否绕过SGA直接从磁盘读Oracle11g取数据。而10g则是全部通过高速缓存读取数据,称为table scan(large)。11g认为大表全表时使用直接路径读,可能比10g中的数据文件散列读(db file scattered reads)速度更快,使用的latch也更少。
大量的direct path read等待时间最可能是一个应用程序问题。 direct path read事件由SQL语句驱动,这些SQL语句执行来自临时的或常规的表空间的直接读取操作。 当输入的内容大于PGA中的工作区域时,带有需要排序的函数的SQL语句将排序结果写入到临时表空间中,临时表空间中的排序顺序串随后被合并,用于提供最终的结果。读取排序结果时,Oracle会话在direct path read等待事件上等待。DB_FILE_DIRECT_IO_COUNT初始化参数可能影响direct path read的性能。
一个隐含参数:
_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
看起来很美 当是它带来另外个等待事件,那就是要把缓存中的脏数据刷回数据文件中。激发check point 事件,DBWR写的任务很频繁。
大量的读IO导致IO缓慢,缓慢的IO又让DBWR写得更慢,同时check point事件会阻塞 DML。 在OLTP方面是很严重的事故。
因为应用程序存在大量的全表查询的语句。
直接路径读/写
通常发生在Oracle直接读数据到进程PGA时,这个读取不需要经过SGA。直接路径读等待事件的3个参数分别是file number(指绝对文件号)、first dba、block cnt数量。在Oracle 10g/11g中,这个等待事件被归于User I/O一类。
db file sequential read、db file scattered read、direct path read是常见的集中数据读方式,下图简要描述了这3种方式的读取示意。
这类读取通常在以下情况被使用:
·磁盘排序IO操作;
·并行查询从属进程;
·预读操作。
最为常见的是第一种情况。在DSS系统中,存在大量的direct path read是很正常的,但是在OLTP系统中,通常显著的直接路径读(direct path read)都意味着系统应用存在问题,从而导致大量的磁盘排序读取操作。
直接路径写(direct paht write)通常发生在Oracle直接从PGA写数据到数据文件或临时文件,这个写操作可以绕过SGA。直接路径写等待事件的3个参数分别是:file number(指绝对文件号)、first dba和block cnt数量,在Oracle 10g/11g中,这个等待事件同direct path read一样被归于User I/O一类。
这类写入操作通常在以下情况被使用:
·直接路径加载;
·并行DML操作;
·磁盘排序;
·对未缓存的“LOB”段的写入,随后会记录为direct path write(lob)等待。
最为常见的直接路径写,多数因为磁盘排序导致。对于这一写入等待,我们应该找到I/O操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。
1. 磁盘排序诊断:
如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑为不同用户分配不同的临时表空间,使用多个临时文件,写入不同磁盘或者裸设备,从而降低竞争,提高性能;对于Oracle 8i的数据库,应该考虑使用本地管理(Local)的临时表空间,而不是字典(dictionary)管理。
对于这种情况,在Oracle 9i之前,可以适当增加sort_area_size的大小;从Oracle 9i开始,可以适当增大pga_aggregate_target,以缩减磁盘排序对于磁盘的写入,从而提高系统及应用响应。但是通常应该及时检查应用,确认是否因为应用问题导致了过度排序,从而根本上解决问题。
2. 并行查询导致性能问题:
有时候在应用系统中,不正确的使用并行查询也会导致应用问题。Statspack的Top 5时间事件输出显示direct path read消耗了较高的等待时,而内存排序率很高甚至是100%(In-memory Sort %:100.00)显然这里的Direct Path Read并不是由于排序引发的,注意到另外一个等待事件(KJC: Wait for msg sends to complete)和并行有关,所以初步判断这里的direct path read可能和并行有关。
注:在Statspack的报告中,存在一个性能指标,称为内存排序率(In-memory Sort Ratio),用于衡量系统的排序操作,这个指标就是由两个统计信息sorts (disk)和sorts (memory)得出:
In-memory Sort Ratio = sorts (......余下全文>>
首先,
这两个查询语句,查询到的结果是不一样的。
第一个语句:
SELECT COUNT(1) FROM DUAL WHERE EXISTS (SELECT 1 FROM XXX WHERE YY IS NOT NULL);结果只能是1或者0。
第二个语句:
SELECT COUNT(1) FROM XXX WHERE YY IS NOT NULL;结果就是xxx表中yy字段不为空的个数。
其次,
如果你只是判断xxx表中yy字段是否有不为空的记录,那么第一个语句效率应该说高一些。
我的理解是这样的,表的block(没有索引的话)肯定是要拿到buffer cache里面(非direct path read),只是当判断的时候会减少一些操作,当执行判断到第一条yy is not null的时候,就不会继续下面的判断操作了。
就算是这样,我觉得效率应该也不会提升多少,顶多也就是节省了cpu的使用。
如果想具体的了解他们两个语句的执行方式,可以开启session的10046事件跟踪一下,比较两个sql语句执行的异同。