以前存储过程中有个大SQL用游标打开后一条条的做处理,
发现数据有好几万条,一条条取再处理有很多fetch,使性能降低,
后来将其改为使用BULK COLLECT一次取几千条,然后批处理,性能提升。可是将这个方法用于用户服务器DB中时,却是第一次较快十分钟左右,可再重跑时就再也不快了(机器与数据库都未再重起,也不能关)??这是为什么?用tkprof查看了一trace,发现跑这个SQL时cpu 200多秒,fetch 17次,都不大呀,
可是disk query都超大,使得elapsed达到15000秒以上难道是因为内存不足吗,因为我一次拿几千条数据在缓存中处理,是不是第一次跑完,内存因为什么原因还没有释放??感觉可能性较小。。
还是数据库本身有坏块之类的倒致很多读操作?
还是其它操作在同时进度所致?因为这个查询本身很快,就拿数据处理的问题才对,所以不应是SQL优化问题,所以我猜测是否还是数据库本身什么地方的问题?!望达人指点!

解决方案 »

  1.   

    FETCH cursor BULK COLLECT INTO ... [LIMIT rows];LZ应该对限制的行数有一个权衡,来合理的利用内存。
      

  2.   

    或许是你的db_cache_size设置得太小,每次查询不足以存放1000条数据所占用数据块。

    Oracle I/O子系统的配置和设计
      

  3.   

    用tkprof查看了一trace,发现跑这个SQL时cpu 200多秒,fetch 17次,都不大呀,
    可是disk query都超大,使得elapsed达到15000秒以上
    LZ可否把trace文件的内容贴一下
      

  4.   


    --参考
    可以考虑将你的表更改为索引组织表(index orgnized table,IOT),既存储在一个索引结构中的表;
    我们常用的存储数据的堆表,数据在堆表中是无组织的存放,只要有空间,数据就可以放在任何地方。
    而IOT则按照数据的主键存储和排序。
    从你的描述中,我看到了每次访问时I/O都特别大,
    可以猜测是访问堆表中的数据花费了很大的时间开销,
    系统并发度越高,堆表使用的cpu时间也会增长得更快,
    而查询耗费cpu时间的原因可能只是在等待缓冲区缓存的闩。
    下面是IOT提供的好处:
    1.提高缓冲区缓存效率,因为给定查询在缓存中需要的块更少。
    2.减少缓冲区缓存访问,这会改善课扩展性
    3.获取数据的物理I/O更少,因为对于任何给定的查询,需要的块更少,
      而且对地址记录的一个物理I/O很可能可以获取所有地址,
      而不只是其中一个地址,但堆表实现就只是获取一个地址。
      

  5.   

    为什么同样的操作第一次快,第二次以后就不快了呢???PGA内存是怎么释放的呀?
    难道真得是内存没释放?