1.行链接与行迁移概念:
行链接:第一次向表中插入数据的时候, 如果一个block不能存放一行记录, 这时Oracle将使用链接一个或者多个在这个段中保留的block存储这一行记录, 行链接产生。因此, 行链接经常发生在有LONG、LONG RAW、LOB等数据类型字段的表上, 例如存放了图片、二进制文档或工程制图等的表。
行迁移:行迁移一般产生在更新操作中, 当更新操作导致行长增加了, 而block的自由空间已经没有, 这时Oracle把整行记录迁移到一个新的block中, 并在原来block中存放新block的链接, 行迁移产生。
行迁移或者行链接发生后, 对该行数据操作的性能就会降低, 因为Oracle必须要扫描更多的block来获得这行的信息。
2.行链接与行迁移的检测
1)创建chained_rows表
利用oracle数据库自身提供的脚本utlchain1sql (在$ORACLE_ HOME / rdbms/admin目录下) 生成chained_rows表, 从建表脚本utlchain1sql 看到, 对于分区 表,cluster 表都是适用的。在大多数数据中心系统中, 预期的海量数据存储均为适用分区表。
2)逐个分析需要检测的表利用ANALYZE TABLE table _ name L IST CHA INEDROWS INTO chained _ rows命令分析表, 分析结果存在chained_ rows表中。
3)查询cha ined_ rows表查询表chained_ rows, 得到表上有多少行链接和行迁移。
3.行链接与行迁移的消除
行链接的消除
行链接主要是由于数据库的db_ block_ size不够大,一行记录数据不能在一个block中完整存储引起的, 因此可以增大db_ block_ size来避免产生行链接, 但是在Oracle9i之前, 数据库建立后db_ block _ size是不可改变的, 只能采取其它变通办法来解决行链接问题, 对于Oracle9i及以后, 是可以支持针对不同的表空间指定不同的db _block_ size的。
可以设置存在分区的表所在的表空间具有更大的db_ block_ size, 比如32KB, 就能解决行链接问题。但是, 放大了db_ block_size, 将会导致存储空间需求成倍增长, 因此, 在实际应用中, 解决行链接问题不能仅靠放大db_ block_ size, 要综合考虑存储空间和系统特性。
行迁移的消除
对于行迁移的清除, 一般来说分为两个步骤:
第一步, 控制住行迁移的增长, 使其不再增多;
第二步, 清除掉以前存在的行迁移。
行迁移产生的主要原因是表中记录更新时block中没有足够的空闲空间引起的, 而要实现第一步控制住行迁移的增长, 就必须为block留出足够的空闲空间, 否则即使清除了当前的行迁移后很快会产生新的行迁移。当然,空闲空间也不是越大越好, 如果设置过大, 会导致空间大量浪费。一般有两种方法来确定空闲空间的大小。
一般是使用微调的方法,监控和调整表的当前pctfree值,每次增加不超过5个百分点, 然后使用ANALYZE TABLETABLE_ NAME L IST CHA INED ROWS INTO chained_ rows命令分析行迁移和行链接的增长情况, 直到表的行迁移基本保持不增长了为止。但是注意也不要把pctfree调的过大, 一般在40%以下, 否则会造成空间的很大浪费和增加数据库访问的I/O。另外种方法是通过计算出来的,但是不一定很准确,一般不适用。
设定空闲空间大小后, 就需要清除表上存在的行迁移了。清除行迁移有很多方法, 下面笔者将逐一介绍这些方法以及它们各自适用的不同情况, 但是这些方法的根本都在于对发生行迁移的数据进行重组。
方法一:传统方法
(1)将表中发生行迁移的记录行放入临时表中保存;
(2)删除原来表中存在行迁移的记录行;
(3)将临时表中的数据重新插入到原来的表中;
(4)删除临时表。
优点是执行起来过程比较简单, 容易实现。缺点一是没有考虑到表关联的情况, 对于有关联的表, 步骤2根本无法执行; 二是这种方法在插入和删除数据的时候都没有disable掉索引, 这样导致时间主要消耗在删除和插入时维持索引树的均衡上, 因此这种方法只能适用于小数据量而且表上无任何外键关联的表。
方法二:改善方法
改进方法与传统方法的区别在于把表中行迁移的行放到临时表以前先把表的外键约束禁用, 在从临时表插回到原表之后再把外键约束启用。这种算法考虑到表之间的关联, 还可以灵活地利用工具生成表的关联信息, 是一种比较适合用于清除行迁移的一种方法。但是这种方法在插入记录和删除记录都是带着索引的, 而且使用这种方法后需要重建关联, 因此此方法不适合表记录太多或者表上的行迁移太多的情况。
方法三:重建表
(1)修改清除行迁移表的名称;RENAME table_ name TO table_ name_ temp;
(2)Drop 所有关联到table_ name的外键限制;
(3)重建1中被rename的表;
(4)插入表中原来的数据;
(5)删除在table_ name_ temp 上的索引和关联其它表的外键;
(6)在table_ name上建立和原来一样的索引、主键和所有的外键限制;
(7)重新编译相关的存储过程、函数和包;
(8)删除表table_ name_ temp。
此方法重建了表、索引和关联, 对于数据库的存储和性能都有提高。但是, 这种方法需要重建一个新表和索引, 因此数据库要有足够空间; 而且对于应用也会有一段时间的中断, 中断时间跟重建索引和关联的多少以及表的记录数量等因素有关。因此, 这种方法对于7 ×24小时应用要求的系统不合适。
方法四:EXP/IMP
(1)使用EXP导出存在有行迁移的表;
(2)然后TRUNCATE原来的表;
(3)IMP导入步骤1导出的表;
(4)重建表上所有的索引(可选, 但是建议重建索引, 否则系统性能不高) 。
由于步骤3较慢, 而且会占用比较大的I/O, 对应用的运行效率会产生影响。此方法的最大缺点是在EXP表的时候要保证该表没有数据的更新或者处于只读状态,否则会导致部分数据的丢失。
方法五:使用MOVE命令
(1)创建新表空间
(2)Move表到步骤1创建的表空间中
(3)重建表上的索引。
上面几种进行数据重组清除行迁移的方法各有优缺点, 分别适用于不同的情况, 对于一个具体问题, 我们一定要认真分析, 针对系统的特点采用不同的清除方法,尽量减少数据库的停用时间, 以保证应用的稳定运行。