简述Oracle IOTIndex Organized Table.docx
- 文档编号:1586445
- 上传时间:2023-05-01
- 格式:DOCX
- 页数:65
- 大小:35.57KB
简述Oracle IOTIndex Organized Table.docx
《简述Oracle IOTIndex Organized Table.docx》由会员分享,可在线阅读,更多相关《简述Oracle IOTIndex Organized Table.docx(65页珍藏版)》请在冰点文库上搜索。
简述OracleIOTIndexOrganizedTable
对关系型数据库产品(RDBMS)而言,一个重要特性就是:
数据信息都被组织为二维数据表,信息的表达可以通过一系列的关联(Join)来完成。
具体数据库产品在实现这个标准的时候,又有千差万别的特点。
就是一个特定的数据库RDBMS产品,往往也提供不同的实现方法。
1、从堆表(HeapTable)到索引组织表(IndexOrganizationTable)
Oracle作为一款成熟的数据库软件产品,就提供了多种数据表存储结构。
我们最常见的就是三种,分别为堆表(HeapTable)、索引组织表(IndexOrganizationTable,简称为IOT)和聚簇表(ClusterTable)。
HeapTable是我们在Oracle中最常使用的数据表,也是Oracle的默认数据表存储结构。
在HeapTable中,数据行是按照“随机存取”的方式进行管理。
从段头块之后,一直到高水位线一下的空间,Oracle都是按照随机的方式进行“粗放式”管理。
当一条数据需要插入到数据表中时,默认情况下,Oracle会在高水位线以下寻找有没有空闲的地方,能够容纳这个新数据行。
如果可以找到这样的地方,Oracle就将这行数据放在空位上。
注意,这个空位选择完全依“能放下”的原则,这个空位可能是被删除数据行的覆盖位。
如果HeapTable段的HWM下没有找到合适的位置,Oracle堆表才去向上推高水位线。
在数据行存储上,HeapTable的数据行是完全没有次序之分的。
我们称之为“随机存取”特征。
对HeapTable,索引独立段的添加一般可以有效的缓解由于随机存取带来的检索压力。
Index叶子节点上记录的数据行键值和Rowid取值,可以让ServerProcess直接定位到数据行的块位置。
聚簇(ClusterTable)是一种合并段存储的情况。
Oracle认为,如果一些数据表更新频率不高,但是经常和另外一个数据表进行连接查询(Join)显示,就可以将其组织在一个存储结构中,这样可以最大限度的提升性能效率。
对聚簇表而言,多个数据表按照连接键的顺序保存在一起。
通常系统环境下,我们使用ClusterTable的情况不太多。
Oracle中的数据字典大量的使用聚簇。
相比是各种关联的基表之间固定连接检索的场景较多,从而确定的方案。
最后就是本系列的IOT(IndexOrganizationTable)。
同ClusterTable一样,IOT是在Oracle数据表策略的一种“非主流”,应用的场景比较窄。
但是一些情况下使用它,往往可以起到非常好的效果。
简单的说,IOT区别于堆表的最大特点,就在于数据行的组织并不是随机的,而是依据数据表主键,按照索引树进行保存。
从段segment结构上看,IOT索引段就包括了所有数据行列,不存在单独的数据表段。
IOT在保存结构上有一些特殊之处,应用在一些特殊的场景之下。
本系列将逐个分析IOT的一些特征,最后讨论我们究竟在什么样的场景下,可以选择IOT作为数据表方案。
2、IOT基础
在创建使用IOT上,我们要强调PrimaryKey的作用。
对一般的堆表而言,PrimaryKey是可有可无的。
一种说法是:
当一个堆表没有设置主键的时候,rowid伪列就是对应的主键值。
而且,PrimaryKey可以在数据表创建之后进行追加设置。
但是,IOT对于主键的设置格外严格,要求创建表的时候就必须指定明确的主键列。
下面我们通过一系列的实验来证明,实验环境为Oracle11g。
SQL>select*fromv$version;
BANNER
------------------------------------
OracleDatabase11gEnterpriseEditionRelease11.2.0.1.0-Production
PL/SQLRelease11.2.0.1.0-Production
CORE11.2.0.1.0Production
我们使用相同的结构,来创建出IOT和HeapTable对照。
--不指定主键,是无法创建IOT;
SQL>createtablem(idnumber)organizationindex;
createtablem(idnumber)organizationindex
ORA-25175:
未找到任何PRIMARYKEY约束条件
在createtable语句后面使用organizationindex,就指定数据表创建结构是IOT。
但是在不指定主键PrimaryKey的情况下,是不允许建表的。
SQL>createtablet_iot(object_idnumber(10)primarykey,object_namevarchar2(100))organizationindex;
Tablecreated
SQL>createtablet_heap(object_idnumber(10)primarykey,object_namevarchar2(100));
Tablecreated
(插入相同数据来源行……)
SQL>execdbms_stats.gather_table_stats(user,'T_IOT',cascade=>true);
PL/SQLproceduresuccessfullycompleted
SQL>execdbms_stats.gather_table_stats(user,'T_HEAP',cascade=>true);
PL/SQLproceduresuccessfullycompleted
从数据字典的层面上,我们分析一下两个数据表的差异,一窥IOT的特点。
SQL>selecttable_name,tablespace_name,blocks,num_rowsfromuser_tableswheretable_namein('T_IOT','T_HEAP');
TABLE_NAMETABLESPACE_NAMEBLOCKSNUM_ROWS
--------------------------------------------------------------------------
T_HEAPSYSTEM15772638
T_IOT72638
SQL>selectsegment_name,blocks,extentsfromuser_segmentswheresegment_namein('T_IOT','T_HEAP');
SEGMENT_NAMEBLOCKSEXTENTS
----------------------------------------
T_HEAP25617
上面两句SQL揭示了几个问题。
首先,Oracle承认IOT是一个数据表,并且统计了数据行数。
但是对数据表的存储表空间和大小没有明确的说明,user_tables视图中这部分的内容为空。
其次,从段结构来看,Oracle明确不承认存在T_IOT段。
因为如果有段segment对象,就意味有空间分配。
但是数据表有数据,是存放在哪里呢?
我们知道,给数据表添加索引的时候,Oracle会自动的添加一个唯一索引。
那么我们去检查一下这部分的结构情况。
SQL>selectindex_name,index_type,table_name,PCT_THRESHOLD,CLUSTERING_FACTORfromuser_indexeswheretable_namein('T_IOT','T_HEAP');
INDEX_NAMEINDEX_TYPETABLE_NAMEPCT_THRESHOLDCLUSTERING_FACTOR
--------------------------------------------------------------------
SYS_C0012408NORMALT_HEAP256
SYS_IOT_TOP_75124IOT-TOPT_IOT500
SQL>selectsegment_name,blocks,extentsfromuser_segmentswheresegment_namein('SYS_C0012408','SYS_IOT_TOP_75124');
SEGMENT_NAMEBLOCKSEXTENTS
----------------------------------------
SYS_C001240825617
SYS_IOT_TOP_7512425617
索引段是存在的,而且明确标注索引类型为IOT索引。
这说明几个问题:
首先,对于IOT而言,只有索引段,没有数据段。
一般的索引而言,叶子节点上只有索引列的取值和rowid。
而对于IOT而言,主键索引上对应就是数据行和索引列取值。
其次,IOT的溢出段阈值(PCT_THRESHOLD)。
这是OracleIOT的特殊策略。
简单的说,当我们把全部数据行保存在叶子节点上,一旦发生主键值的变化、新值插入、删除等动作,索引叶子块的分裂动作是频繁的。
数据行保存在叶子节点上只会让这样的分裂动作更加频繁和后果严重。
Oracle提出将一部分的非主键列单独存储,这个参数就是比例值。
最后,我们探讨一下IOT索引的ClusteringFactor。
ClusteringFactor是反映索引叶子节点顺序和数据保存行直接离散程度的综合性指标。
一般来说,堆表的ClusteringFactor是随着DML操作不断退化的过程。
ClusteringFactor是影响到Oracle索引路径成本的一个重要参数(IOT的索引这部分的值永远为0,因为索引的顺序就是数据行的顺序,两者存储顺序相同,绝对一致。
3、IOT与执行计划
在IOT数据表下,我们通常的执行计划会如何呢?
普通HeapTable和IOT在这部分的差异很大。
通常而言,HeapTable的索引路径伴随着两次段结构的读取——索引段和数据段。
先读取索引段段头,经历根节点、分支节点、叶子节点,最后获取到结果集合rowid列表。
之后进行回表操作,使用rowid依次查询数据表的行。
但是IOT表可以不同。
索引和数据保留在一起,理论上拿到了叶子节点,也就是拿到了数据行。
IOT是不存在回表操作的,所以相对heaptable来说,回表部分成本是节省的。
下面我们通过执行计划,来看IOT的特征。
SQL>explainplanforselect*fromt_iotwhereobject_id=1000;
Explained
SQL>select*fromtable(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Planhashvalue:
2277898128
--------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Tim
---------------------------------------------------------------------------
|0|SELECTSTATEMENT||1|11|1(0)|00:
|*1|INDEXUNIQUESCAN|SYS_IOT_TOP_75124|1|11|1(0)|00:
-------------------------------------------------------------------------------
PredicateInformation(identifiedbyoperationid):
---------------------------------------------------
1-access("OBJECT_ID"=1000)
13rowsselected
SQL>explainplanforselect*fromt_iot;
Explained
SQL>select*fromtable(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
Planhashvalue:
4201110863
-------------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|
-------------------------------------------------------------------------------
|0|SELECTSTATEMENT||72638|780K|47(0)|
|1|INDEXFASTFULLSCAN|SYS_IOT_TOP_75124|72638|780K|47(0)|
------------------------------------------------------------------------
8rowsselected
对于IOT,我们要保证访问的数据表的方式是主键路径为主。
在上面的两个执行计划中,我们按照主键进行检索,路径为IndexUniqueScan。
全表扫描为IndexFastFullScan。
两者都没有明显的回表动作。
试想,如果数据表较小,IndexFullScan也是IOT表常常出现的执行路径。
对一般的HeapTable,执行路径如何呢?
SQL>explainplanforselect*fromt_heapwhereobject_id=1000;
Explained
SQL>select*fromtable(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
Planhashvalue:
1833345710
-----------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)
---------------------------------------------------------------------------
|0|SELECTSTATEMENT||1|11|2(0)
|1|TABLEACCESSBYINDEXROWID|T_HEAP|1|11|2(0)
|*2|INDEXUNIQUESCAN|SYS_C0012408|1||1(0)
--------------------------------------------------------------------------
PredicateInformation(identifiedbyoperationid):
---------------------------------------------------
2-access("OBJECT_ID"=1000)
14rowsselected
SQL>explainplanforselect*fromt_heap;
Explained
SQL>select*fromtable(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Planhashvalue:
1253663840
---------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|
----------------------------------------------------------------------------
|0|SELECTSTATEMENT||72638|780K|42(0)|00:
00:
01|
|1|TABLEACCESSFULL|T_HEAP|72638|780K|42(0)|00:
00:
01|
----------------------------------------------------------------------------
8rowsselected
普通堆表都不能避免出现回表动作。
最后,我们要声明一下回表动作的成本影响。
IOT和HeapTable一个很大的执行计划差异,就是回表。
但是从成本上计算,CBO并不是因为回表动作才确定执行计划,而是ClusteringFactor的影响。
对堆表而言,ClusteringFactor都是一个很大的问题,无论是CBO的成本公式上,还是不断Degrade的前景。
IOT一个突出优势就是直接消灭了ClusteringFactor的成本因素。
但是这也就带来一个问题,一个数据表只能按照主键的顺序进行组织,辅助索引(SecondaryIndex)的问题是很多版本Oracle和IOT使用者争议的话题。
SecondaryIndex问题我们在后面会继续讨论到。
简述OracleIOT(IndexOrganizedTable)(中)2012-10-0420:
17:
39
分类:
Linux
上篇中我们简单介绍了一下IOT的基本知识和概念。
本篇继续来介绍IOT相关的内容。
4、IOT日常维护
相对于堆表heap结构,索引组织表最大的特点在于将数据行全部内容作为叶子节点保存在索引结构中。
IOT中只包括索引段(IndexSegment)结构,没有对应的数据表段(TableSegment)结构。
在日常运维工作中,我们经常需要对索引结构进行定期的重构rebuild操作,来消除索引无效节点(DeadNode)。
那么,IOT结构中,我们维护工作需要注意些什么问题呢?
我们依然使用上篇的IOT数据表T_IOT和堆表T_HEAP来进行比对实验。
SQL>selectindex_namefromuser_indexeswheretable_name='T_IOT';
INDEX_NAME
------------------------------
SYS_IOT_TOP_75124
数据表T_IOT对应的主键索引名称为SYS_IOT_TOP_75124。
该索引段大致空间为2M。
SQL>desct_iot;
NameTypeNullableDefaultComments
-----------------------------------------------
OBJECT_IDNUMBER(10)
OBJECT_NAMEVARCHAR2(100)Y
SQL>selectcount(*)fromt_iot;
COUNT(*)
----------
72638
SQL>selectsegment_name,bytes/1024/1024fromuser_segmentswheresegment_name='SYS_IOT_TOP_75124';
SEGMENT_NAMEBYTES/1024/1024
---------------------------------------------
SYS_IOT_TOP_751242
我们删除一批数据,形成死叶子节点。
SQL>deletet_iotwhererownum<40000;
39999rowsdeleted
SQL>commit;
Commitcomplete
SQL>execdbms_stats.gather_table_stats(user,'T_IOT',cascade=>true);
PL/SQLproceduresuccessfullycompleted
SQL>selectsegment_name,bytes/1024/1024fromuser_segmentswheresegment_name='SYS_IOT_TOP_75124';
SEGMENT_NAMEBYTES/1024/1024
---------------------------------------------
SYS_IOT_TOP_751242
数据行被删除,索引段HWM没有收缩。
我们可以使用analyzeindex命令进行索引健康程度检查。
SQL>analyzeindexSYS_IOT_TOP_75124validatestructure;
Indexanalyzed
Q
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 简述Oracle IOTIndex Organized Table 简述 Oracle