索引组织表其实就是存储在一个索引结构中的表
一般我们在oracle数据库中,用到的都是堆组织表,而在mysql常用引擎innodb中的表就是索引组织表,今天因为业务需要,测试了下oracle的索引组织表
需求是这样的,将有几十亿数据的A表的新字段cc更新为一个新值(蛋疼的需求),这个值来自数据仓库统计得到的一个B表,A.ID与B.ID关联,需要将B表拉到A表所在的库。如果使用常规的方法,将B表拉过来,然后还需要创建 id,cc两个字段的联合索引,这样将消耗大量的空间,并且索引大小会比表还大。所以直接创建id为主键的IOT表,一举两得,唯一的问题可能是在创建这个IOT表的开销会比堆表要大。
--处理超级大量数据时,需要使用extent分块来做,这个是必须的 O(∩_∩)O
在正式开始之前,先对iot和堆表进行一个简单的比较,以便心中有数。
--常规堆表
CREATE TABLE tmp_xf (
id NUMBER,
PARENT_ID NUMBER,
NICK VARCHAR2(32),
GMT_MODIFIED DATE,
PRIMARY KEY (id))
TABLESPACE tbs_crm_dat;
alter SESSION enable parallel dml;
要在dml中开启并行,需要把这个参数打开
INSERT /*+ parallel(a,8) */ INTO tmp_xf aSELECT /*+ parallel(t,8) */ id,PARENT_ID,NICK,GMT_MODIFIED FROM test_order t;15mins简单粗暴的导入方式,耗时15分钟。从并行度可以看到是8个seleclt 8个insert
--索引组织表
CREATE TABLE tmp_xf_iot (
id NUMBER,
PARENT_ID NUMBER,
NICK VARCHAR2(32),
GMT_MODIFIED DATE,
PRIMARY KEY (id))
ORGANIZATION INDEX
TABLESPACE tbs_crm_dat;
14:46:41 SQL> INSERT /*+ parallel(a,8) */ INTO tmp_xf_iot a
14:47:03 2 SELECT /*+ parallel(t,8) */ id,PARENT_ID,NICK,GMT_MODIFIED FROM test_order t;
100501397 ROWS created.
Elapsed: 00:33:41.04
耗时33分钟,是常规表的两倍多,这个时间是可以接受的。毕竟数据导入的同时相当于在维护索引,而且过程中数据在不停的移动。
=======================分割线 一点都不华丽==========
读取对比
-----堆表
11:35:32 SQL> SELECT * FROM tmp_xf WHERE id = 2165985;
ID PARENT_ID NICK GMT_MODIFIED
---------- ---------- -------------------------------- -------------------
2165985 0 twork_mengdie13 2010-10-26,16:43:17
Elapsed: 00:00:00.01
Execution PLAN
----------------------------------------------------------
PLAN hash VALUE: 1973243085
---------------------------------------------------------------------------------------------
| Id | Operation | Name | ROWS | Bytes | COST (%CPU)| TIME |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 53 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TMP_XF | 1 | 53 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C00131311 | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
STATISTICS
----------------------------------------------------------
5 consistent gets
可以看到根据主键访问需要5个逻辑读,分析索引的高度是blevel是3,高度high是4,通过索引拿到rowid是4个逻辑读,在回表的话就是5个逻辑读
--索引组织表
11:41:01 SQL> SELECT * FROM tmp_xf_iot WHERE id = 2165985;
ID PARENT_ID NICK GMT_MODIFIED
---------- ---------- -------------------------------- -------------------
2165985 0 twork_mengdie13 2010-10-26,16:43:17
Elapsed: 00:00:00.00
Execution PLAN
----------------------------------------------------------
PLAN hash VALUE: 1560068715
----------------------------------------------------------------------------------------
| Id | Operation | Name | ROWS | Bytes | COST (%CPU)| TIME |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 53 | 1 (0)| 00:00:01 |
|* 1 | INDEX UNIQUE SCAN| SYS_IOT_TOP_249218 | 1 | 53 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
STATISTICS
----------------------------------------------------------
4 consistent gets
4个逻辑读,很好理解,索引的高度是一样的,只是少了回表。 哈哈,因为数据都在索引了,不存在回表的概念了。
--具体的操作记录后续更新...
小结:合理的使用索引组织表,可以提高效率,节省空间,但索引组织表也是存在很多限制的,特别是oracle的索引组织表,因为没有实在的物理rowid,只存在逻辑rowid,在索引组织表上再建索引需要额外的考虑。
推荐看看下面的资料
oracle编程艺术 http://blog.csdn.net/knowhow/archive/2008/01/13/2042277.aspx 表 索引章节
杨老大的 索引组织表中逻辑ROWID的物理猜 http://yangtingkun./post/468/503568