jinyuan oracle,简述Oracle IOT(Index Organized Table)(下)
下面我们讨论一下由于数据存储为索引而带来的Rowid、问题。
6、Logical Rowid & Secondary
Index
在的环境下,我们是不能保证一个固定的物理Rowid的。
堆表()中,一行数据被保存在一个物理位置(file no. + block
no.)之后,在正常保存行为中,即使发生行迁移现象,它的rowid是不会发生变化的。只有在进行数据表存储重构,如move和shrink
space的时候才会发生新的rowid赋予。
堆表rowid的固定给我们带来一个好处,就是连带的数据表索引叶子节点上面的的rowid永远有效的,除非发生move或者和shrink
space操作(此时索引失效)。
但是,IOT存在一些问题。索引叶子节点的分裂操作是相当频繁的,我们很难保证一个数据行维持在一个rowid不会发生大的变化。当然,如果我们保证每次访问数据表都是通过主键primary
key方式,变化的rowid不会有任何影响。问题出在非主键的索引,IOT中称之为“二级索引”Secondary
Index上。
对于一般的二级索引,如果叶子节点上保留数据行的rowid,那么失效的rowid意味着所有对应的二级索引非常容易变为invalid状态。
在很多数据库版本,包括早期的版本中,对于Secondary
Index是不支持的。最近的oracle中,引入了Logical
Rowid和Physical
Guess的方法,才最终解决了Secondary
Index问题。
SQL> select rowid,
object_id from t_iot where rownum<5;
ROWIDOBJECT_ID
-------------------------------
-----------
*BABBVmoCwQP+2
*BABBVmoCwQT+3
*BABBVmoCwQX+4
*BABBVmoCwQb+5
对IOT而言,rowid基本上是不合乎我们常见的heap table
rowid格式的。我们可以对t_iot添加secondary
index。
SQL> create index
idx_t_iot_name on t_iot(object_name);
Index
created
SQL> exec
dbms_stats.gather_table_stats(user,'T_IOT',cascade =>
true);
PL/SQL procedure successfully
completed
从数据字典中看,索引idx_t_iot_name没有什么额外的差异,只是对于一般索引来说,取值略高。
SQL> select index_Name,
index_type, clustering_factorfrom dba_indexes where
wner='SYS' and index_name='IDX_T_IOT_NAME';
INDEX_NAMEINDEX_TYPECLUSTERING_FACTOR
------------------------------
--------------------------- -----------------
IDX_T_IOT_NAMENORMAL55006
SQL> select count(*) from
t_iot;
COUNT(*)
----------
72604
SQL> select
sum(bytes)/1024/1024, count(*) from dba_extents where wner='SYS'
and segment_name='IDX_T_IOT_NAME';
SUM(BYTES)/1024/1024COUNT(*)
--------------------
----------
419
对于一个7万余条记录的数据表索引,占到了19个分区,总看空间4M。那么,如果是一般的heap table
index呢?空间如何?
SQL> desc
t_heap;
NameTypeNullable
Default Comments
----------- -------------
-------- ------- --------
OBJECT_IDNUMBER(10)
OBJECT_NAME VARCHAR2(100)
Y
SQL> create index
idx_t_heap_name on t_heap(object_name);
Index
created
SQL> select count(*) from
t_heap;
COUNT(*)
----------
72605
SQL> select
sum(bytes)/1024/1024, count(*) from dba_extents where wner='SYS'
and segment_name='IDX_T_HEAP_NAME';
SUM(BYTES)/1024/1024COUNT(*)
--------------------
----------
318
相同取值,正常index只有3M空间,约占到18个分区。说明:Secondary
Index对比一些其他索引,有很多特殊的信息在其中。
SQL> col object_name for
a20;
SQL> select object_id,
object_name from dba_objects where object_name in
('IDX_T_HEAP_NAME','IDX_T_IOT_NAME');
OBJECT_ID
OBJECT_NAME
----------
--------------------
75146
IDX_T_HEAP_NAME
75143
IDX_T_IOT_NAME
我们尝试将两个索引树dump出来,探索其结构差异。
SQL> select value from
v$diag_info where name='Default Trace File';
VALUE
--------------------------------------------------------------------------------
/u01/diag/rdbms/wilson/wilson/trace/wilson_ora_9101.trc
--堆表索引结构
SQL> alter system set
events 'immediate trace name treedump level75146';
System
altered
--IOT表索引结构
SQL> alter system set
events 'immediate trace name treedump level75143';
System
altered
首先,我们分析一下一般堆表的索引情况。由于篇幅原因,只截取部分内容。
*** ACTION NAME:(Command
Window - New) 2012-10-05 02:43:39.561
----- begin tree
dump
branch:0x415c01 4283393(0: nrow: 2, level:
2)
branch:0x415d3b
4283707(-1: nrow: 312, level: 1)
leaf:0x415c02
4283394(-1: nrow: 184 rrow: 184)
leaf:
0x415c03 4283395 (0: nrow: 184 rrow: 184)
leaf:
0x415c04 4283396 (1: nrow: 188 rrow: 188)
leaf:
0x415c05 4283397 (2: nrow: 190 rrow: 190)
leaf:
0x415c06 4283398 (3: nrow: 184 rrow: 184)
leaf:
0x415c07 4283399 (4: nrow: 186 rrow: 186)
leaf:
0x415c08 4283400 (5: nrow: 185 rrow: 185)
从Dump结果上,我们可以清晰看到IDX_T_HEAP_NAME是一个两层索引结构。根节点地址为0x415c01(file=1,
block=89089)。
SQL> select
to_number('415c01','xxxxxx') from dual;
TO_NUMBER('415C01','XXXXXX')
----------------------------
4283393
其中的一个数据块0x415c06进行试验,转化为十进制地址为4283398,二进制地址为:10000010101110000000110。根据rfile解析规则,最终地址为:file_no=1,block_no=89094。
SQL> alter system dump
datafile 1 block 89094;
System
altered
Dump文件中叶子节点的内容为:
row#0[8000] flag: ------,
lock: 0, len=32
col 0; len 22;
(22):
2f 31 34 64 63 62 36
32 32 5f 53 79 6e 74 68 4c 61 62 65 6c 55 49
col 1; len 6;
(6):00 41
55 91 00 4b
row#1[7968] flag: ------,
lock: 0, len=32
col 0; len 22;
(22):
2f 31 34 64 63 62 36
32 32 5f 53 79 6e 74 68 4c 61 62 65 6c 55 49
col 1; len 6;
(6):00 41
55 91 00 4c
row#2[7928] flag: ------,
lock: 0, len=40
col 0; len 30;
(30):
2f 31 34 65 33 63 31
31 32 5f 50 4e 47 45 6e 63 6f 64 65 50 61 72 61 6d
50
61 6c 65 74
74
col 1; len 6;
(6):00 41
5b 9a 00 9d
从结构上猜测,col0和col1分别表示索引列取值和对应rowid信息。而IOT的secondary
index如何呢?
*** 2012-10-05
02:43:55.944
----- begin tree
dump
branch: 0x4154b9 4281529 (0:
nrow: 2, level: 2)
branch:
0x415acd 4283085 (-1: nrow: 330, level: 1)
leaf:
0x4154ba 4281530 (-1: nrow: 160 rrow: 160)
leaf:
0x4154bb 4281531 (0: nrow: 158 rrow: 158)
leaf:
0x4154bc 4281532 (1: nrow: 163 rrow: 163)
leaf:
0x4154bd 4281533 (2: nrow: 162 rrow: 162)
leaf:
0x4154be 4281534 (3: nrow: 163 rrow: 163)
leaf:
0x4154bf 4281535 (4: nrow: 160 rrow: 160)
leaf:
0x4154c0 4281536 (5: nrow: 159 rrow: 159)
leaf:
0x4154c1 4281537 (6: nrow: 161 rrow: 161)
leaf:
0x4154c2 4281538 (7: nrow: 160 rrow: 160)
叶子节点0x4154bc,对应具体的二进制为:10000010101010010111100。分析获得的位置为:file_no=1,block_no=87228。
我们将该块dump出。
SQL> alter system dump
datafile 1 block 87228;
System
altered
row#0[7986] flag: K-----,
lock: 0, len=46
col 0; len 30;
(30):
2f 31 32 30 66 34 37
30 38 5f 46 75 6c 6c 48 54 4d 4c 44 6f 63 75 6d 65
6e
74 61 74 69
6f
col 1; len 4;
(4):c3 04
39 24
tl: 8 fb: --H-FL--
lb: 0x0cc:
1
col0: [ 4]00 41 59
3e
row#1[7940] flag: K-----,
lock: 0, len=46
col 0; len 30;
(30):
2f 31 32 30 66 64 37
36 64 5f 4f 72 61 63 6c 65 44 61 74 61 62 61 73 65
4d
65 74 61 44
61
col 1; len 4;
(4):c3 02
50 1a
tl: 8 fb: --H-FL--
lb: 0x0cc:
1
col0: [ 4]00 41 54
a1
row#2[7894] flag: K-----,
lock: 0, len=46
col 0; len 30;
(30):
2f 31 32 30 66 64 37
36 64 5f 4f 72 61 63 6c 65 44 61 74 61 62 61 73 65
4d
65 74 61 44
61
col 1; len 4;
(4):c3 04
4c 1a
tl: 8 fb: --H-FL--
lb: 0x0cc:
1
col0: [ 4]00 41 54
a2
上面标红的部分是我们看到了和Heap Index的差异,正式由于这部分信息的差异,才让IOT Secondary
Index体积略大。
从概念上,Secondary Index包括三部分叶子节点内容:索引键值、logical
rowid和对应数据行的主键值。在进行检索的时候,Oracle首先用logical
rowid进行初步的试探,看看对应的位置是否可以找到对应数据。这个过程我们称为physical
guess。
如果找到了对应数据行,那么皆大欢喜。如果没有,oracle就只能通过数据行的主键值,进行IOT索引树定位。这个过程,要重复多读一个段结构。
具体Secondary Index的分析,留待下次进行更加详细的说明。
7、IOT的使用
我们已经在一个系列中,详细介绍了IOT的特性,最后我们聊一聊IOT应用的场景。总的来说,笔者认为IOT在一般系统的应用中,是没有很广泛的发挥场景的。在没有明确的分析和POC实验基础上,我们不要轻易进行IOT决策。具体来说,有如下的几点:
üIOT环境下,有更多的限制
我们常使用的堆表,虽然有各种问题,但是是目前我们可以得到的适应性最广,优化策略最多的一种表存储结构。IOT则要受到很多的限制,例如:IOT必须要制定主键,也就是定义出核心访问方式;PCTThreshold参数如果设置了,但是没有指定overflew
segment,那么超出阈值的数据行是不会被接受,要抛出异常。IOT表中分区和Lob类型不能同时使用。IOT维护工作要更多。
ü单一读取,读多写少的操作类型
我们定义出IOT后,实际上就是规定了数据表的核心访问方式。当我们使用主键条件时,IOT可以方便的帮助我们定位记录。但是其他查询条件应用secondary
index的效率就是一个问题。而且secondary
index也是不久前才支持的Oracle特性。如果我们的数据表应用是一个多种检索方式并存的操作表,那么IOT不是理想的选择。
索引操作本身对增加、修改和删除等DML操作是具有性能影响的。在IOT环境下,这种影响只会让其更加剧烈。所以,如果数据表不是很少修改的数据表,那么使用IOT不是最好的选择。
ü主键列和列数目的约束
索引叶子节点中就能将所有数据行列保存在叶子节点上。而索引叶子节点是变化分裂频繁的对象。所以,如果数据行列数很多,或者数据主键列相对很小,那么IOT的效果是不好的。
8、结论
Heap,IOT和Cluster是数据表的三大基本存储类型。我们在实际中,要把握原则是:以堆表为核心,默认都使用Heap
Table。如果在架构分析、性能测试和试运行阶段,发现性能问题,可以考虑使用IOT或者Cluster。但是,在选型的时候,一定要明确两种表结构的优缺点和适用范围。
jinyuan oracle,简述Oracle IOT(Index Organized Table)(下)相关推荐
- IOT(Index Organized Table)
我们知道一般的表都以堆(heap)的形式来组织的,这是无序的组织方式.Oracle还提供了一种有序的表,它就是索引组织表,简称IOT表.IOT表上必须要有主键,而IOT表本身不对应segment,表里 ...
- 索引组织表(index organized table, IOT)
1.索引组织表 索引组织表(index organized table, IOT)就是存储在一个索引结构中的表.存储在堆中的表是无组织的(也就是说,只要有可用的空间,数据可以放在任何地方),IOT中的 ...
- oracle索引组织表(Index Organizied Table)
索引组织表(index organized table, IOT)就是存储在一个索引结构中的表.存储在堆中的表是无组织的(也就是说,只要有可用的空间,数据可以放在任何地方),IOT中的数据则按主键存储 ...
- oracle rebuild online,alter index rebuild
Oracle alter index rebuild 说明[日期:2011-06-12]来源:Linux社区 作者:tianlesoftware[字体:大中小] 一.官网说明 在MOS 上的一篇文章讲 ...
- oracle full table scan,ORACLE优化之执行规划(1) - TABLE FULL SCAN/INDEX FULL SCAN
ORACLE优化之执行规划(1) - TABLE FULL SCAN/INDEX FULL SCAN TABLE FULL SCAN 全表扫描,表示表中所有记录都被访问到.如果表很大, 该操作对查询性 ...
- oracle12178错误,Oracle学习笔记_20080522:Index FS vs Index FFS
Index Full Scan vs Index Fast Full Scan index full scan和index fast full scan是指同样的东西吗?答案是no.两者虽然从字面上看 ...
- ORACLE虚拟索引(Virtual Index)
ORACLE虚拟索引(Virtual Index) 虚拟索引概念 虚拟索引(Virtual Indexes)是一个定义在数据字典中的假索引(fake index),它没有相关的索引段.虚拟索引的目 ...
- oracle imp导入时出现skipping table
最近有同事在使用传统的imp工具导入数据时,总是提示收到skipping table的提示,也就是表被跳过,而不是被重建.即使是将目标数据库上的表对象删除,仍然无法导入.因此记录一下,供大家参考. 1 ...
- 简述oracle数据库特殊状态,【OracleDB】 01 概述和基本操作
实例概念: Oracle有一个特殊的概念 Oracle数据库 = 数据库 + Oracle文件系统 + Oracle实例 实例处理Oracle的请求,调用文件系统 然后返回结果响应给客户端 单实例和多 ...
最新文章
- Michael Jordan:当下的AI其实都是伪“AI”
- 改进博客园Markdown显示功能(加代码行号、显示代码所用编程语言)
- swagger 修改dto注解_Swagger 详解
- 美团多渠道打包原理以及使用
- 文都计算机统考讲义,考研计算机文都基础班讲义.doc
- 积分兑换平台(这是一种剥削么?强烈求拍砖)
- Android service Binder用法
- Nginx教程1:基本概念
- docker中启动Springboot时异常之Failed to instantiate [com.zaxxer.hikari.HikariDataSource]
- linux安装安卓fastboot,Android的fastboot协议
- (研究向)如何使用Windows任务管理器看BadApple
- 统计学中p值计算公式_统计学中的P值应该怎么计算
- 矩阵的LU分解——MATLAB实现
- SQL分组统计-每个学科前三名
- 通过网页端保存ins图片的方法(谷歌浏览器)
- 一个非常有意思的网站
- 字符串库函数(1)Strlen,strcpy,strcat,strcmp
- golang学习资源
- 深度学习基础篇【5】从0开始搭建YOLOV5 并进行测试
- python自动投递_利用python如何在前程无忧高效投递简历