调整归档时第一件需要确保的事是LGWR没有等待ARCn完成归档一个日志文件第二个需要考虑的是ARCn活动时的影响对前台进程最小化而这两个方面通常是刚好相对的因此最好的目标就是调整ARCn使其足够快并在可以证明其影响了前台进程时降低其速度主要包括以下原则另外还包括归档可用的缓沖大小和数量的调整以及归档进程的数量 缓沖的大小 ARCn每次从日志文件读取 _log_archive_buffer_size(以块为单位)并写入归档目的地因此如果_log_archive_buffer_size设置为OS下最大的可能值那么ARCn的性能将最大化并且其在I/O子系统上的负载将最小化如果该参数在OS上为UNLIMITED那么设置为最大的物理I/O大小的几倍效果将最好 缓沖的数量 如果_log_archive_buffers可用并且可以从日志文件异步读取那么ARCn将使用aio_read()系统调用并行读取日志到多个缓沖如果多个日志成员可用将使用并行异步读每个日志文件成员以扩展磁盘I/O负载如果使用了软件/硬件镜像进行日志文件传播类似的负载平衡将会自动由软件/硬件使用因此可以考虑使用并行归档读使用与每个日志文件相同多的磁盘镜像或者传播然后配置_log_archive_buffers最多为 需要注意的是不能通过设置多个_arch_io_slaves来模麓尤罩疚募稍辈⑿幸觳蕉痢RCn通常自己执行该任何并仅使用I/O服务器来写操作 为了在可能时进行异步归档写至少需要设置两个_log_archive_buffers以并行从日志文件读取但是如果系统达到了cpu负载颈瓶并且归档期间前台进程受到了影响并且没有归档聚集的威胁应该考虑减少缓沖数量分散cpu负载 进程数量 如果产生的重做持续过高或者需要归档到多个位置通常需要多个ARCn进程从Oraclei开始可以通过设置log_archive_max_processes参数也可以通过定期调度ALTER SYSTEM ARCHIVE LOG ALL如果没有归档聚集该命令的影响是很小的但是如果有该命令会迅速产生额外的arcn帮助赶上聚集 为了防止LGWR赶上归档聚集运行多个ARCn是最大的保险但是为了使该策略有效恰当的配置在线日志和归档终点的磁盘是很重要的 因为也可以使用手工归档Oracle在归档期间将在任何在线日志文件上保留一个排斥的WL(等待日志)队列锁而忽略log_archive_max_processes的设置这些队列上的操作由archive control latch保护归档活动可以从STATSPACK等报告中的该LARCHE上的gets列得到 影响归档进程性能的两个威胁 在RAC环境下在实例没有启动时其线程是可用的如果一个关闭的启用的线程的当前SCN落后于force scn那么在那个线程上将发生强制的日志切换并且活动实例的ARCn为未活动的实例归档日志文件这使得arcn进程转移到那个实例中工作而不是执行其自己的工作然而如果ARCn被其自己的lgwr唤醒归档其自己实例的日志那么ARCn将会刮起这个归档这应该通过保持空闲实例启动或者禁用其重做线程完全避免 归档在前项滚动期间将被完全禁用因此应该确保干净的关闭保持重做产生最小化 通用的索引块头 header address =xcc kdxcolev KDXCOLEV Flags = kdxcolok kdxcoopc x: opcode=: iot flags= is converted=Y kdxconco kdxcosdc kdxconro kdxcofbo =x kdxcofeo =x kdxcoavs kdxcolev索引级别(代表页块) kdxcolok标示结构块事块是否发生 kdxcoopc内部操作码 kdxconco索引列数量包括ROWID kdxcosdc块中索引结构改变的数量 kdxconro索引条目的数量不包括kdxbrlmc指针 kdxcofbo块中空闲空间的开始位置 kdxcofeo块中空闲空间的结束位置 kdxcoavs块中的可用空间数量(kdxcofbokdxcofeo) 分支头区域 kdxbrlmc =x kdxbrsno kdxbrbksz kdxbrlmc如果索引值小于第一个值(row#)则为该索引值所在的块地址 kdxbrsno最后更改的索引条目 kdxbrbksz可使用的块空间 叶块头区域 kdxlespl kdxlende kdxlenxt =xb kdxleprv =xd kdxledsz kdxlebksz kdxlespl块拆分时被清除的未提交数据的字节数 kdxlende被删除的条目数 kdxlenxt下一个页块的RBA kdxleprv上一个页块的RBA kdxlebksz可使用的块空间(默认小于分支的可用空间) 分支条目 row#[] dba: =x col ; len ; (): c col ; TERM row#[] dba: =x col ; len ; (): c col ; TERM 行号[块中的起始位置] dba 列号列长度列值 brach中的每个entry有个columns: 一个是child blocks中的最大值另一个是指向的下一层block的address 但是某些时候可能会有一些比较奇怪的结果 row#[] dba: =xc col ; len ; (): … col ; len ; (): end of branch block dump 叶条目 row#[] flag: S lock: len= col ; len ; (): c col ; len ; (): db a row#[] flag: DS lock: len= 行号[在块中的开始位置] 各种标记(锁信息删除信息) 索引列号长度值其中个字节的为ROWID号将其转换为二进制算法结果为 前 bit代表了file_id 中 bit代表了block_id 后 bit代表了row_id 通过文件号和块号算出的结果为创建该索引的表的块 奇怪的是为什么索引中的rowid不能直接找到obj_id? 因为索引段对应的数据段在 一开始就知道因为是先知道数据段才找到索引段然后 根据索引段内容去搜索数据段内容所以索引段中 rowid 不必包含 data_object_id 信息 如果索引是建立在非分区表上或者是分区表上的 LOCAL 索引使用的是 bytes的 Restricted ROWID如果索引是建立在分区表上的 GLOBAL index则使用 bytes 的 Extended ROWID这样可以区分索引指向哪个分区表 更新/重用索引条目 当更新了索引条目后DUMP如下 kdxconco kdxcosdc kdxconro kdxcofbo =x kdxcofeo =xf kdxcoavs kdxlespl kdxlende kdxlenxt =x kdxleprv =x kdxledsz kdxlebksz row#[] flag: D lock: => deleted index entry col ; len ; (): f col ; len ; (): a row#[] flag: lock: col ; len ; (): a => new index entry col ; len ; (): a 更新后将包含一个删除的条目一个新的条目在随后的插入中如果新插入的索引条目能够放到被删除的索引条目的位置上就会直接重用这个条目根据索引值来决定 所谓重用是对row 的重用而不是对row所在物理存储(或说物理位置)的重用索引是按照indexed value对row进行排序的有新的row被插入首先按照value排序将他放在合适的row list中如果他的位置正好原来有个row被删掉了则重用这个row在row list中的位置至于物理存储上则可能根据版本不同会有不同在中我做的测试并没有向下开辟空间 结论: ·到叶块中的任何插入都将移除所有被删除的条目 ·删除的空间在随后的写中被清除 ·删除的空间在延迟块清除中被清除 ·全空块被放在空闲列表可以重用 索引统计 ·dba_indexes ·dbms_stats ·index_stats analyze index index_name validate structure; 分析资源锁 ·v$segment_statistics statistics_level = typical (or all) 注意事项 blevel (dba_indexes) vs height (index_stats) blocks allocated但未必使用 lf_rows_len包含行负载(单列索引个字节) pct_used索引结构中当前使用的空间(used_space/btree_space)* 绝大多数索引统计包含删除的条目 nondeleted rows = lf_rows – del_lf_rows pct_used by nondeleted rows = ((used_space – del_lf_rows_len) / btree_space) * |