神秘的oracle查询

时间:2011-03-18 09:08:42

标签: sql oracle query-optimization

如果oracle中的查询第一次执行11分钟,而下一次,同一查询25秒,缓冲区被刷新,可能的原因是什么?可能是查询写得不好吗?

set timing on;
set echo on
set lines 999;

insert into elegrouptmp select idcll,idgrpl,0 from elegroup where idgrpl = 109999990;
insert into SLIMONTMP (idpartes, indi, grecptseqs, devs, idcll, idclrelpayl)
    select rel.idpartes, rel.indi, rel.idgres,rel.iddevs,vpers.idcll,nvl(cdsptc.idcll,vpers.idcll)
from
    relbqe rel,
    elegrouptmp ele,
    vrdlpers vpers
    left join cdsptc cdsptc on
            (cdsptc.idclptcl = vpers.idcll and
             cdsptc.cdptcs      = 'NOS')
where
    rel.idtits = '10BCPGE ' and
    vpers.idbqes = rel.idpartes and
    vpers.cdqltptfc = 'N' and
    vpers.idcll = ele.idelegrpl and
    ele.idgrpl = 109999990;

alter system flush shared_pool;
alter system flush buffer_cache;
alter system flush global context;

select /* original */ mvtcta_part_SLIMONtmp.idpartes,mvtcta_part_SLIMONtmp.indi,mvtcta_part_SLIMONtmp.grecptseqs,mvtcta_part_SLIMONtmp.devs,
mvtcta_part_SLIMONtmp.idcll,mvtcta_part_SLIMONtmp.idclrelpayl,mvtcta_part_vrdlpers1.idcll,mvtcta_part_vrdlpers1.shnas,mvtcta_part_vrdlpers1.cdqltptfc,
mvtcta_part_vrdlpers1.idbqes,mvtcta_part_compte1.idcll,mvtcta_part_compte1.grecpts,mvtcta_part_compte1.seqc,mvtcta_part_compte1.devs,mvtcta_part_compte1.sldminud,
mvtcta.idcll,mvtcta.grecptseqs,mvtcta.devs,mvtcta.termel,mvtcta.dtcptl,mvtcta.nusesi,mvtcta.fiches,mvtcta.indl,mvtcta.nuecrs,mvtcta.dtexel,mvtcta.dtvall,
mvtcta.dtpayl,mvtcta.ioi,mvtcta.mtd,mvtcta.cdlibs,mvtcta.libcps,mvtcta.sldinitd,mvtcta.flagtypei,mvtcta.flagetati,mvtcta.flagwarnl,mvtcta.flagdonei,mvtcta.oriindl,
mvtcta.idportfl,mvtcta.extnuecrs
from SLIMONtmp mvtcta_part_SLIMONtmp
left join vrdlpers mvtcta_part_vrdlpers1 on
(
   mvtcta_part_vrdlpers1.idbqes = mvtcta_part_SLIMONtmp.idpartes
   and mvtcta_part_vrdlpers1.cdqltptfc = 'N'
   and mvtcta_part_vrdlpers1.idcll = mvtcta_part_SLIMONtmp.idcll
)
left join compte mvtcta_part_compte1 on
(
   mvtcta_part_compte1.idcll = mvtcta_part_vrdlpers1.idcll
   and mvtcta_part_compte1.grecpts = substr (mvtcta_part_SLIMONtmp.grecptseqs, 1, 2 )
   and mvtcta_part_compte1.seqc = substr (mvtcta_part_SLIMONtmp.grecptseqs, -1  )
   and mvtcta_part_compte1.devs = mvtcta_part_SLIMONtmp.devs
   and (mvtcta_part_compte1.devs = ' ' or ' ' =  ' ')
   and mvtcta_part_compte1.cdpartc not in ( 'L' , 'R' )
)
left join mvtcta mvtcta on
(
   mvtcta.idcll = mvtcta_part_SLIMONtmp.idclrelpayl
   and mvtcta.devs = mvtcta_part_SLIMONtmp.devs
   and mvtcta.grecptseqs = mvtcta_part_SLIMONtmp.grecptseqs
   and mvtcta.flagdonei <> 0
   and mvtcta.devs = mvtcta_part_compte1.devs
   and mvtcta.dtvall > 20101206
)
where 1=1
order by mvtcta_part_compte1.devs,
mvtcta_part_SLIMONtmp.idpartes,
mvtcta_part_SLIMONtmp.idclrelpayl,
mvtcta_part_SLIMONtmp.grecptseqs,
mvtcta.dtvall;

6 个答案:

答案 0 :(得分:4)

  

“如果oracle中的查询采用第一个查询   时间执行11分钟,而且   下一次,同样的查询25   秒,缓冲区   脸红了,可能的原因是什么?“

问题是,像这样刷新数据库缓冲区......

alter system flush shared_pool
/

...擦除Oracle数据存储,但还有其他地方可以缓存数据。例如,您的操作系统可能会缓存其文件读取。

EXPLAIN PLAN可以作为数据库认为它将如何执行查询的一般指南,但它只是一个预测。它可能会因糟糕的统计数据或环境条件而被抛弃。它不擅长解释为什么查询的特定实例花费的时间和它一样多。

因此,如果您真的想了解数据库执行特定查询时发生的情况,您需要了解并弄脏它,并学习如何使用等待接口。这是一种非常强大的跟踪机制,它允许我们查看在单个查询执行过程中发生的各个事件。每个版本的Oracle都扩展了等待接口的实用性和丰富性,但是自从Oracle 9i(如果不是更早的话)以来,它对于正确调整至关重要。

通过阅读Roger Schrag's very good overview 了解更多信息。

在您的情况下,您需要多次运行跟踪。为了便于比较结果,您应该为每次执行使用单独的会话,每次都设置10046事件。

答案 1 :(得分:0)

当你运行这些时,盒子上还发生了什么?您可以根据咀嚼资源的其他流程获得不同的时间。此外,通过大量连接,性能将取决于内存使用情况(hash_area_size,sort_area_size等)和可用性,因此您可能正在进行分页(也请检查临时空间大小/用法)。简而言之,尝试sql_trace和tkprof来深入分析

答案 2 :(得分:0)

有时在提交之前将一个块写入文件系统(一个脏块)。当稍后读取该块时,Oracle发现它是未提交的。它检查打开的事务,如果事务不在那里,它知道更改已提交。因此,它将块写回一个干净的块。它被称为延迟块清除。

这是第一次读取块的速度比后续重新读取速度慢的一个可能原因。

答案 3 :(得分:0)

可能是第二次知道执行计划。也许优化器由于某种原因很难找到执行计划。 尝试设置

alter session set optimizer_max_permutations=100;

并重新运行查询。看看这是否有所不同。

答案 4 :(得分:0)

could it be that the query is written in a bad way?

&#34;坏&#34;是一种相当情绪化的表达 - 但从广义上讲,是的,如果查询在第二次运行时表现得更快,通常意味着有多种方法可以优化查询。

实际上,优化查询是 - 正如APC所说 - 而是一个关于&#34; down和dirty&#34;的问题。你的例子中明显的候选人可能是子串 - 如果表是巨大的,并且子串错过了索引,我想象这将需要一些时间,并且我想象所有这些子包的结果操作缓存在某个地方。

答案 5 :(得分:0)

这是Tom Kyte's take on flushing Oracle buffers as a testing practice。我只想说他不是粉丝。他倾向于尝试使用您的测试数据(“现实生活”)来模拟您的生产负载,并抛弃第一次和最后一次运行。 @ APC关于操作系统缓存的观点是汤姆的观点 - 要摆脱那些(非平凡的!)效果,你需要反弹服务器,而不仅仅是数据库。