在知道了cachelatch的数量以后,我们只需要用hash chain的数量除以latch的数量以后,就可以算出每个latch管理多少个hash chain了 。我们将下面7532除以1024,就可以知道,当前的系统中,每个latch大概对应8个hash chain 。
SQL> select x.ksppinm, y.ksppstvl, x.ksppdesc2from x$ksppi x , x$ksppcv y3where x.indx = y.indx4and x.ksppinm like '\_%' escape '\'5and ksppinm like '%_db_block_hash_buckets%'6;KSPPINMKSPPSTVL KSPPDESC---------------------- -------- -------------------------------------_db_block_hash_buckets 7523Number of database block hash buckets
当数据库在hash chain搜索需要的数据块时,必须先获得cachelatch 。然后在扫描hash chain的过程中会一直持有该latch,直到找到所要的数据块才会释放该latch 。当有进程一直在扫描某条hash chain,而其他进程也要扫描相同的hash chain时,其他进程就必须等待类型为cachelatch的latch free等待事件 。
不够优化的SQL语句是导致cachelatch的主要原因 。如果SQL语句需要访问过多的内存数据块,那么必然会持有latch很长时间 。找出逻辑读特别大的sql语句进行调整 。v$里那些/为较大值的SQL语句就是那些需要调整的SQL语句 。这种方式不是很有针对性,比较盲目 。
网上曾经有人提供了一个比较有针对性的、查找这种引起较为严重的cachelatch的SQL语句的方式,其原理是根据latch的地址,到x$bh中找对应的 ,x$bh的表示该 所对应的latch地址 。然后根据 可以找到所对应的表的名称 。最后可以到v$(也可以到stats$)中找到引用了这些表的SQL语句 。我也列在这里 。where条件中的
select /**//*+ rule */ s.sql_textfrom x$bh a,dba_extents b,(select * from (select addr from v$latch_childrenwhere name = 'cache buffers chains' order by sleeps desc)where rownum<11) c,v$sqltext swhere a.hladdr = c.addrand a.dbarfil = b.relative_fnoand a.dbablk between b.block_id and b.block_id + b.blocksand s.sql_text like '%'||b.segment_name||'%' and b.segment_type='TABLE'order by s.hash_value,s.address,s.piece/
还有一个原因可能会引起cachelatch,就是热点数据块问题 。这是指多个重复访问一个或多个被同一个child cachelatch保护的内存数据块 。这主要是应用程序的问题 。大多数情况下,单纯增加child cache的个数对提高性能没有作用 。这是因为内存数据块是根据数据块地址以及hash chain的个数来进行hash运算从而得到具体的hash chain的,而不是根据child cache的个数 。如果数据块的地址以及hash chain的个数保持一致,那么热点块仍然很有可能会被hash到同一个child cachelatch上 。可以通过v$的p1raw字段来判断latch free等待事件是否是由于出现了热点块 。如果p1raw保持一致,那么说明在等待同一个latch地址,系统存在热点块 。当然也可以通过x$bh的tch来判断是否出现了热点块,该值越高则数据块越热 。
SQL> select sid, p1raw, p2, p3, seconds_in_wait, wait_time, state2fromv$session_wait3whereevent = 'latch free'4order by p2, p1raw;SID P1RAWP2P3 SECONDS_IN_WAITWAIT_TIME STATE---- -------- --- --- --------------- ---------- ------------------38 6666535C 13112 WAITED KNOWN TIME42 6666535C 13112 WAITED KNOWN TIME44 6666535C 13314 WAITED KNOWN TIME………………………85 6666535C 133112 WAITED KNOWN TIME214 6666535C 138112 WAITED KNOWN TIME
接下来,我们就可以根据p1raw的值去找到所对应的内存数据块以及对应的表的名称了 。
select a.hladdr, a.file#, a.dbablk, a.tch, a.obj, b.object_namefromx$bh a, dba_objects bwhere(a.obj = b.object_idora.obj = b.data_object_id)anda.hladdr = '6666535C';
要解决热点块的问题,可以通过将热点块中的行分散到多个数据块中去,这样原来的热点块就变成了多个数据块,这样被hash到同一个latch的几率就降低了 。如果热点块属于表,则可以先将表的数据导出来,然后增加表的值,最后将数据再导入 。如果热点块属于索引,则可以设定较高的 参数后,重建索引 。注意,这会增加索引的高度 。
- 深度学习基础:压缩视频增强调研
- 深度学习中Epoch,Batchsize,Iterations
- 一文读懂深度学习中的Epoch,Batchsize
- 深度学习概念之Epoch,Batch Size和Iterations
- 一文理解深度学习中的BN,LN,IN,GN,SN的归一化操作
- 深度学习_经典网络_ResNet详解及常见问题总结
- 三 深度学习笔记:神经网络之九种激活函数Sigmoid、tanh、ReLU、R
- 五 花书读书笔记-深度前馈网络
- 深度学习-第R1周心脏病预测
- ARXIV:深度学习在金融领域中的应用 | 唧唧堂论文解析