首页 > 编程知识 正文

oracle 命令行登录(oracle表索引个数)

时间:2023-05-05 09:20:22 阅读:103193 作者:3175

作者简介

平安科技数据库技术专家盛世月饼,深耕数据库行业十余年,对Oracle数据库兴趣浓厚,对MySQL、MongoDB、Redis等数据库的架构和运维有一定经验。目前沉迷于PostgreSQL数据库和Oracle数据库的PK,专注于关系数据库分布式架构的研究。

介绍

Oracle数据库被设计成一个高度共享的数据库。这里所说的“共享”可以从数据库共享内存、后台进程、游标、执行计划、锁存器等方面来理解。Oracle设计的目的是以最小的系统开销最大限度地支持更多的并发会话。也正是基于这样的设计思路,所以Oracle单实例的纵向扩展能力一直是DB领域的佼佼者。

之前看过PGyxdsn的文章,分析了为什么Oracle的CursorPin S不会出现在PostgreSQL中。主要原因是PostgreSQL的执行计划不是全局共享的,Oracle中的同一个Cursor可以在不同的会话中共享(Oracle在一定条件下也会触发重硬解析)。客观来说,这种设计其实各有利弊。虽然PG的计划缓存没有被不同的会话共享,避免了高并发时不同的会话对同一个游标的争用,但也意味着在相同并发会话数的情况下,PG的会话需要更多的缓存,每个会话至少要解析一次。或者反过来说,在相同资源约束的前提下,Oracle支持的并发数更高。

引用Oracle高级驱动Oracle 7的OCP的一段话:“早期的Oracle使用的是会话私有内存,但是当负载并发增加时,内存消耗就成了问题,执行计划无法共享,解析时间的增加率极大地影响了OLTP系统的整体执行时间。因此,基于这一点,Oracle进行了优化,包括会话缓存游标和共享池,减少了SQL执行过程中的解析时间和规划时间。但是没有免费的午餐,肯定会有其他消耗,类似内存结构并发保护的代价。简而言之:

会话级SQL解析是Oracle采用的第一项技术。

任何应用程序都应该根据它所使用的数据库的特性进行良好的设计。

这里不讨论哪个数据库更NB。每种数据库技术的发展都会受到很多因素的影响,包括业务战略、市场需求、软硬件技术成熟度等。我们采用Oracle已经很多年了,对Oracle数据库也有很深的感情,但目前我们也毫不犹豫地致力于开源数据库和NoSQL。技术有好有坏,最好的就是最适合应用场景的最好的。在这里,我们只关注Oracle数据库的这些“共享”资源遇到高并发时出现问题的原因和对策。

我们说的是想法,不是具体的订单。

这里的处理方法是基于对过去发生的实际案例的总结。

高并发DML导致的问题

Oracle的表是堆表,索引是B树。对表进行DML时,Oracle会同时操作表的块和维护索引树的块。然后,当大量会话需要同时维护索引(或表)的同一块时,索引(或表)上就会出现争用。发生争用时,v$session_wait显示当前会话正在等待的事件名称。

1enq: TX -分配ITL条目

此等待事件表示当前会话正在等待块(可能是表块或索引块)上方的事务槽分配。

可能的原因有:

初始变速器设置太小。

并发DML太高,ITL插槽被其他会话占用,尚未释放,此块上没有可用空间来添加新的ITL插槽,因此当没有可用的ITL插槽时,后续会话只能等待。

设置合理,并发性不是很高。但是,运行报表的效率发生了变化,导致持有ITL的时间变长,进而导致后续的拥堵。

解决方案:

对于现有索引,请在重建时重建并增加initrans,例如,从16-32-64(如果在重建索引时增加pct可用空间,则在重建后会为每个块保留更多的可用空间,但它可能会被后续索引的维护占用)。

创建新索引并修改数据库开发规范。创建新索引时,默认initrans为16;

一般上述问题在Table块中很少出现,但是我们的一个非常高频的更新表在生产过程中也遇到了这个问题,所以最后修改了规范,在创建新表时默认将initrans指定为6。

如果确认sql语句效率下降导致HOLTL时间变长,那么分析sql效率下降的原因并进行优化。

小知识点:

如果您在v$lock中看到会话正在请求lmode为4的锁,原因之一可能是ITL等待,其他原因可能是并发操作主键、位图索引、分布式事务等。

2enq: TX -索引争用

当表处于高并发插入操作中,等待字段类型为日期和自增序列的索引块时,通常会出现此问题。因为应用程序总是插入最新的(高关键)值,所以这些索引通常向右倾斜增长,也就是说,近期最频繁的操作发生在索引的最右边一页。

子块上,叶子块的free空间很快被填满,然后叶子块要分裂,分裂过程总要去找free block,index spliter的进程会持有一个enq:TX锁,其它并发insert的进程一般也正是需往最右边的这个index leaf block去insert数据,所以都要等待这个spliter进程完成并释放这个锁。(竞争更加激烈时,甚至会在branch block的split时产生)

解决思路:

删除无用索引。为什么把这个显而易见的措施放到第一位呢,其实是有来由的。很多开发人员其实并不知道一个表上若创建过多索引会对DML产生影响,只知道创建索引对查询带来帮助,有些夸张的甚至会为一个表的每个列上都创建单列或组合索引。但是事实证明,经过DBA的采样监控,很多索引可能一年半载都不会被用到,那么还不删除这些索引更待何时?

将索引改造为hash分区索引。原理是可以打散并发操作的叶子节点。

将索引改造为反序索引。原理同上,因为是reverseindex,同样可以打散high key的叶子节点。

设置更小的block size,比如8k -> 4k - 2k。原理一样,因为更小的索引block里面存放的条目更少,理论上减少了两个不同会话同时访问同一个block的几率,进而减少了争用。但是这个方案其实会有其它副作用,除非其它方案都不能考虑,否则不建议这个方案。

重建索引。 为什么重建索引对这个问题能够带来帮助呢,因为重建索引后减少了索引的碎片,索引block变得更加紧凑,减少了index leaf block split时寻找空块的时间,提高了Oracle进行索引分裂时的效率,进而可以减少等待时间。

如果index contention的对象不是leaf block,而是rootblock,则可以考虑通过以下方法激活索引的root block分裂时的优化:

1)alter system set events '43822 trace name context forever,level1';

2)event 43822启用后,对于root block的split进行了增强, 不会超过5次的index block reclamation,Oracle就会去申请分配新块了。

背景知识:

Oracle在索引split时中寻找可复用的free block的过程如下:

Oracle不会一开始就让index segment申请分配新的空间(这会造成index segment的空间过度增长) ,而是到该index segment的其它地方搜索是否存在可用的Free Block, 这些Free Block的要求是status是75%-100% Free的, server process会扫描这些75%-100% Free的block 并确认这些block 实际上是100%空的, 如果找到100% Free Block则使用;如果没有则继续搜索, 直到所有候选block都被检查过,这个行为叫做 probes on index block reclamation。每次寻找空块并failed ,oracle就会增加这个统计指标: “failed probes on index block reclamation”。Oracle内部机制会控制要找多少次,不会去FULL SCAN所有index block的,failed超过一定次数后就会申请分配新的block。

不能重用的原因有2个:

可能这个块不是100%free的,而是70% ~ <100% free的, 也就是找到的这个block上面还有几行或者多行索引记录,所以不能被重用来做split。

可能这个块上还有一些其它的active transaction,所以它重用不了。

在这个过程中,Oracle还有机会找到的block其实已经是索引结构中的一个非空block,但是Oracle只会在splittingand relinking to index structure之后才会发现这个block其实是illegal的选择,这个时候Oracle会回滚这个操作,这个统计记录在‘transaction rollback’ in v$sysstat,然后继续寻找另外一个block。

Oracle进行找空块的过程中,如果这些块不在内存中,会增加物理读,如果这些块还需要做延迟块清除或者还要回滚,则需要触发更多系统递归操作,可见,如果“failed probes”过多,split效率低下时,会直接导致index contention增加。

3enq: HW –contention

TABLE的High WaterMark(即高水位线)标识table segment中已用空间和未用空间的边界,具体来讲,HWM以上的block的状态是:unformattedand have never been used; HWM以下的block的状态是:Allocated, but currentlyunformatted and unused、 Formatted and contain data、Formatted and empty because the data was deleted。当HWM以下的block都无空闲空间可以使用时,Oracle会推进HWM来申请分配新的block到segment里面,而HW enqueue锁被用来管理推进HWM分配新空间时的串行操作。

显而易见,当高并发的insert发生时,甚至表中若有LOB字段时情况更糟,HWM的推进分配新空间的速度赶不上并发会话所需空间的速度时,就会发生在HW的enq上的等待。

解决思路:

删除无用索引。

改造为hash分区表。同一时间的并发的空间分配需求会被打散到多个分区段上。

提前手工allocatenew空间(可以做成定期自动任务)。

主动shrink回收可以重用的空间,避免业务高峰期的自动allocate竞争。

设置表空间更大的UNIFORM SIZE,每次allocate更多extent到表的HWM之上,避免HWM剧烈时偶尔还会等在表空间的extent分配上。

确保使用ASSM (Automatic segment spacemanagement) tablespace。

隐含参数_bump_highwater_mark_count,可以控制HWM每次推进的block个数。但是设置该隐含参数应该得到Oracle的支持,而且对其它小表有负面影响。

检查IO子系统性能,有时候IO性能的变化也会导致空间分配操作缓慢,进而引发等待。

LOB段空间的频繁重回收,可能也会导致该竞争,针对LOB可以适当增加chunk,每次分配更多空间;也可以主动allocate 或shrink

另外针对使用ASSM表空间的LOB有一个Bug 6376915注意检查是否已applied fixed patch,并且要通过设置event来启用。此event用于控制1次LOB chunk回收操作时的chunk个数(default是1),进而可以减少HWM enq等待发生的次数。

EVENT="44951 TRACE NAME CONTEXT FOREVER, LEVEL < 1 -1024 >"

4enq: US –contention

这个等待事件通常说明会话在等待Undo Segment,注意等待的原因一般其实并不是因为UNDO TABLESPACE没有空间了,UNDO表空间不足会直接报ORA-30036(NOSPACEERRCNT)。

造成这个等待的典型场景有:

如果UNDO表空间是AUTOEXTEND的,则Oracle会自动调整undo retention,在尽量保持retention参数设定的undo block保留期的基础上,还会尽量满足一些长查询的读一致性需求。那么当这个特性发挥作用时,很多UNDO segment都被用在了长查询(MAXQUERYLEN)的支持上,当突发很多并发会话同时需要申请分配undo segment时,Oracle的回收机制(UNXPSTEAL)就会捉襟见肘。

大量active的undo block正在回滚、无法重用,可能是由于不久之前刚kill了一个长事务造成的。

也可能是虽然有空闲空间,但是由于应用重启、或者准点抢售类的应用导致高并发事务进入数据库后,短暂时间内需要将大量的undo seg从offline变成online,而smon没有处理得那么快,故可能出现短暂的大量enq:US-contention,这个时候通常会伴随大量的'latch: rowcache objects'(on DC_ROLLBACK_SEGMENTS)。我们的一个保险类系统在双11抢售时后台数据库就曾经出现过这个问题。

解决思路:

如果预期要做抢售活动,可以提前维护,设置_ROLLBACK_SEGMENT_COUNT为一个较高的值,保持一定数量的undosegments始终是online状态。

设置event让SMON不会自动将undo segment OFFLINE:

alter system set events '10511 trace name context forever, level1 ';

将_UNDO_AUTOTUNE临时设置为FALSE,以避免当UNDO TBS很空闲时,Oracle自动将undo retention调得很大,提前占用过多undo segments。

设置_HIGHTHRESHOLD_UNDORETENTION,虽然允许Oracle自动调整undo retention,但是为它设置一个天花板,不会过份地受MAXQUERYLEN的影响。

本文重要提示:

上述所有隐含参数的介绍,一方面是为了加深对Oracle相关管理机制的了解,另一方面都是在常规手段包括应用层调优的手段无法奏效的前提下的应急方案,在生产环境启用之前请得到Oracle原厂的确认与支持,而且在高峰期或问题应急解决后务必要取消隐参。

不要随意在生产环境使用隐含参数,这是一个最基本的数据库运维原则!

总结

上面这些问题的解决思路其实都是治标不治本的,这些优化措施可能能够帮助你的系统度过当前的系统波峰,但是随着时间的推移当更大的波峰出现时,问题还会再次发生。优化“对数据库的需求”带来的效果永远大于优化“数据库所能提供的资源”,虽然有时候优化“对数据库的需求”的成本投入更高,但是投入与产出一般都是成正比的。从这个意义上来讲,若应用能够合理控制并发、系统架构中引入缓存层、采用异步队列处理机制、优化DB模型设计以及SQL写法等,这才是解决问题的根本之道。

精选专题(官网:dbaplus.cn)

◆ 近期热文 ◆

解密网易MySQL实例迁移高效完成背后的黑科技

从SQL Server到MySQL,4款主流迁移工具到底哪家强?

从DBA管理角度,看12c那些令人倾心的内存新特性

如何用一款小工具大大加速MySQL SQL语句优化

从微软和小米的转型之痛,解读DevOps落地的核心要点

◆ 专家专栏 ◆

调皮的毛巾丨yedbks丨陈能技丨ggdkf丨xndhy丨thdjw

魏兴华丨甜甜的寒风丨周正中丨炙热的睫毛膏丨白鳝丨虚拟的黑夜丨阳光的钢笔/p>

◆ 近期活动 ◆

Gdevops全球敏捷运维峰会上海站

峰会官网:www.gdevops.com

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。