ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 简述Oracle IOT(Index Organized Table)(中)

简述Oracle IOT(Index Organized Table)(中)

Linux操作系统 作者:壹頁書 时间:2014-02-05 09:21:14 0 删除 编辑

 

上篇中我们简单介绍了一下IOT的基本知识和概念。本篇继续来介绍IOT相关的内容。

 

4IOT日常维护

 

相对于堆表heap结构,索引组织表最大的特点在于将数据行全部内容作为叶子节点保存在索引结构中。IOT中只包括索引段(Index Segment)结构,没有对应的数据表段(Table Segment)结构。

 

在日常运维工作中,我们经常需要对索引结构进行定期的重构rebuild操作,来消除索引无效节点(Dead Node)。那么,IOT结构中,我们维护工作需要注意些什么问题呢?

 

我们依然使用上篇的IOT数据表T_IOT和堆表T_HEAP来进行比对实验。

 

 

SQL> select index_name from user_indexes where table_name='T_IOT';

 

INDEX_NAME

------------------------------

SYS_IOT_TOP_75124

 

 

数据表T_IOT对应的主键索引名称为SYS_IOT_TOP_75124。该索引段大致空间为2M

 

 

SQL> desc t_iot;

Name        Type          Nullable Default Comments

----------- ------------- -------- ------- --------

OBJECT_ID   NUMBER(10)                             

OBJECT_NAME VARCHAR2(100) Y                        

 

SQL> select count(*) from t_iot;

  COUNT(*)

----------

     72638

 

SQL> select segment_name, bytes/1024/1024 from user_segments where segment_name='SYS_IOT_TOP_75124';

 

SEGMENT_NAME                   BYTES/1024/1024

------------------------------ ---------------

SYS_IOT_TOP_75124                            2

 

 

我们删除一批数据,形成死叶子节点。

 

 

SQL> delete t_iot where rownum<40000;

39999 rows deleted

 

SQL> commit;

Commit complete

 

SQL> exec dbms_stats.gather_table_stats(user,'T_IOT',cascade => true);

PL/SQL procedure successfully completed

 

SQL> select segment_name, bytes/1024/1024 from user_segments where segment_name='SYS_IOT_TOP_75124';

 

SEGMENT_NAME                   BYTES/1024/1024

------------------------------ ---------------

SYS_IOT_TOP_75124                            2

 

 

数据行被删除,索引段HWM没有收缩。我们可以使用analyze index命令进行索引健康程度检查。

 

 

SQL> analyze index SYS_IOT_TOP_75124 validate structure;

Index analyzed

 

 

QL> select height, blocks, name, lf_rows, DEL_LF_ROWS, pct_used from index_stats;

 

    HEIGHT     BLOCKS NAME                  LF_ROWS DEL_LF_ROWS   PCT_USED

---------- ---------- ------------------------------ ---------- ----------- ----------

         2        256 SYS_IOT_TOP_75124            72638       39999         90

 

 

index_stats视图中,我们可以清晰看到有接近四万叶子节点是Dead状态,索引树高度为2。我们进行索引rebuild,是常用的整理索引操作。

 

 

SQL> alter index SYS_IOT_TOP_75124 rebuild;

alter index SYS_IOT_TOP_75124 rebuild

 

ORA-28650: IOT 中的主索引不能重建

 

SQL> alter table t_iot disable constraint SYS_IOT_TOP_75124;

alter table t_iot disable constraint SYS_IOT_TOP_75124

 

ORA-25188: 对于索引表或排序散列簇, 无法删除/禁用/延迟主键约束条件

 

 

常用的rebuild操作不能使用在IOT主键索引中,而且disable索引也没有办法实现。整理IOT的方法,可以选择数据表的move方法。

 

 

SQL> alter table t_iot move;

 

Table altered

 

SQL> exec dbms_stats.gather_table_stats(user,'T_IOT',cascade => true);

 

PL/SQL procedure successfully completed

 

SQL> select segment_name, bytes/1024/1024 from user_segments where segment_name='SYS_IOT_TOP_75124';

 

SEGMENT_NAME                   BYTES/1024/1024

------------------------------ ---------------

SYS_IOT_TOP_75124                       0.6875

 

 

整理数据表t_iot move操作后,索引高水位线下降。

 

 

SQL> analyze index SYS_IOT_TOP_75124 validate structure;

 

Index analyzed

 

SQL> select height, blocks, name, lf_rows, DEL_LF_ROWS, pct_used from index_stats;

 

    HEIGHT     BLOCKS NAME                    LF_ROWS DEL_LF_ROWS   PCT_USED

---------- ---------- ------------------------------ ---------- ----------- ----------

         2         88 SYS_IOT_TOP_75124            32639           0         89

 

 

从分析结果看,我们消除了死叶子节点。那么,我们是否可以对数据表开启row movement呢?这个操作是move操作的替代品。

 

 

SQL> alter table t_iot enable row movement;

alter table t_iot enable row movement

 

ORA-14066: 未分区的索引表的选项非法

 

SQL> alter table t_heap enable row movement;

Table altered

 

 

从实验结果看,row movement不能应用到IOT上。

 

 

5IOT Index Overflow Segment

 

IOT表而言,我们需要考虑Overflow Segment的问题。B树索引叶子节点存在一个长期让我们争议的问题,就是叶子块分裂、合并的问题。

 

索引结构成树过程和维持过程,是一个索引树不断分裂叶子节点、拷贝数据的过程。当一个新叶子节点值加入索引树的时候,索引结构需要将其有序的分配在特定的叶子“位置”上。这点和堆表heap table的随机保存策略差异很大。如果这个位置所在的数据块已经写“满”,就需要进行数据块分裂(5/5算法或者9/1算法),找一个新的空白块,将溢出的数据叶子节点信息写入到新块中。这个过程同时伴随着分支节点的调整。

 

维持B树平衡过程是很复杂的过程,一般数据表为了维持对应索引的同步结构通常要损失一个数量级的DML操作效率。

 

对于IOT来说,这种B树平衡过程代表更加复杂的消耗。因为IOT表的所有数据行都要保存在叶子块中,维持树过程中的拷贝和分裂操作更加剧烈。Oracle为了缓解这个情况,引入了IOT Overflow Segment概念。

 

通常来说,我们使用IOT表是需要进行考量的。我们很倾向选择数据主键列相对较大,列数相对较少的数据表作为IOT表。同时,读多写少也是IOT的重要定性指标。

 

Overflow Segment(溢出段)的理念很简单,通过设置一个阈值(PCTThreshold),来规定将数据行转移存储位置。如果我们将PCTThreshold值设置为10,那么如果一个数据行空间占有比例超过了10%数据块大小,非主键列都会被“溢”出到IOT索引之外进行保存。这个溢出空间我们称之为“Overflow Segment”,我们也可以为溢出段指定单独的表空间进行保存。

 

Overflow Segment存在的表空间,我们称之为Overflow Segment Tablespace。下面我们创建一个全新的IOT,设置专门的PCTThreshold值。

 

 

 

SQL> create table t_iotbig

  2  (object_id number primary key,

  3   object_name varchar2(200),

  4   object_type varchar2(100),

  5   EDITION_NAME varchar2(100),

  6   last_ddl_time date)

  7  organization index tablespace users

  8  pctthreshold 5

  9  overflow tablespace example;

 

Table created

 

 

SQL> insert into t_iotbig select object_id, object_name, object_type, edition_name, last_ddl_time from dba_objects;

72604 rows inserted

 

SQL> commit;

Commit complete

 

SQL> exec dbms_stats.gather_table_stats(user,'T_IOTBIG',cascade => true);

PL/SQL procedure successfully completed

 

 

数据表段(本质是索引段)所在表空间指定,是通过organization index tablespace指定的。Pctthreshold参数来指定溢出段阈值,我们试验中设置为5%。溢出段overflow segment通过overflow tablespace来指定。

 

装载约7万余条数据之后,我们检查数据段的情况。

 

 

SQL> col tablespace_name for a10;

SQL> col iot_name for a10;

SQL> select table_name, tablespace_name, num_rows, iot_type, iot_name from dba_tables where wner='SYS' and table_name='T_IOTBIG';

 

TABLE_NAME                     TABLESPACE   NUM_ROWS IOT_TYPE     IOT_NAME

------------------------------ ---------- ---------- ------------ ----------

T_IOTBIG                                       72604 IOT         

 

 

SSQL> select index_name, index_type, PCT_THRESHOLD, tablespace_name from dba_indexes where table_name='T_IOTBIG' and wner='SYS';

 

INDEX_NAME         INDEX_TYPE                  PCT_THRESHOLD TABLESPACE

------------------------------ --------------------------- ------------- ----------

SYS_IOT_TOP_75137              IOT - TOP                               5 USERS

 

 

索引具备属性pct_threshold=5。同时,我们在dba_tables中,可以看到溢出段的情况。

 

 

SQL> select table_name, tablespace_name, iot_name, iot_type from dba_tables where wner='SYS' and iot_name='T_IOTBIG';

 

TABLE_NAME                     TABLESPACE IOT_NAME   IOT_TYPE

------------------------------ ---------- ---------- ------------

SYS_IOT_OVER_75137             EXAMPLE    T_IOTBIG   IOT_OVERFLOW

 

 

在数据表视图中,我们发现IOT_NAME中对应IOT数据表名称的对象中,存在一个特殊的隐含数据表,命名为系统自动命名。这个数据表和IOT不同,明确表示存在表空间EXAMPLE中,IOT_TYPE也明确标注出IOT_OVERFLOW类型。

 

我们从段空间分配的角度,看IOTT_IOTBIG的情况。

 

 

SQL> select segment_name, segment_type, tablespace_name, extents, blocks from dba_segments where wner='SYS' and segment_name in ('SYS_IOT_OVER_75137','SYS_IOT_TOP_75137','T_IOTBIG');

 

SEGMENT_NAME         SEGMENT_TYPE       TABLESPACE    EXTENTS     BLOCKS

-------------------- ------------------ ---------- ---------- ----------

SYS_IOT_TOP_75137    INDEX              USERS              20        640

SYS_IOT_OVER_75137   TABLE              EXAMPLE             1          8

 

 

dba_segments中,可以清楚看到IOT表的空间使用情况:索引段是有空间分配的、溢出段也是有空间分配的。而且两者可以在不同的表空间。

 

 

参数pctthreshold是可以指定这个溢出段阈值。如果不指定,Oracle会选择一个默认值50%。我们的IOTt_iot就是这样的方式。

 

 

SQL> select index_name, index_type, PCT_THRESHOLD, tablespace_name from dba_indexes where table_name='T_IOT' and wner='SYS';

 

INDEX_NAME                     INDEX_TYPE                  PCT_THRESHOLD TABLESPACE

------------------------------ --------------------------- ------------- ----------

SYS_IOT_TOP_75124              IOT - TOP                              50 SYSTEM

 

SQL> select count(*) from dba_tables where wner='SYS' and iot_name='T_IOT';

 

  COUNT(*)

----------

         0

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29254281/viewspace-1077187/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    621
  • 访问量
    5955641