索引組織表其實就是存儲在一個索引結構中的表
一般我們在oracle數(shù)據(jù)庫中,用到的都是堆組織表,而在mysql常用引擎innodb中的表就是索引組織表,今天因為業(yè)務需要,測試了下oracle的索引組織表
需求是這樣的,將有幾十億數(shù)據(jù)的A表的新字段cc更新為一個新值(蛋疼的需求),這個值來自數(shù)據(jù)倉庫統(tǒng)計得到的一個B表,A.ID與B.ID關聯(lián),需要將B表拉到A表所在的庫。如果使用常規(guī)的方法,將B表拉過來,然后還需要創(chuàng)建 id,cc兩個字段的聯(lián)合索引,這樣將消耗大量的空間,并且索引大小會比表還大。所以直接創(chuàng)建id為主鍵的IOT表,一舉兩得,唯一的問題可能是在創(chuàng)建這個IOT表的開銷會比堆表要大。
--處理超級大量數(shù)據(jù)時,需要使用extent分塊來做,這個是必須的 O(∩_∩)O
在正式開始之前,先對iot和堆表進行一個簡單的比較,以便心中有數(shù)。
--常規(guī)堆表
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中開啟并行,需要把這個參數(shù)打開
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分鐘,是常規(guī)表的兩倍多,這個時間是可以接受的。畢竟數(shù)據(jù)導入的同時相當于在維護索引,而且過程中數(shù)據(jù)在不停的移動。
=======================分割線 一點都不華麗==========
讀取對比
-----堆表
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
可以看到根據(jù)主鍵訪問需要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個邏輯讀,很好理解,索引的高度是一樣的,只是少了回表。 哈哈,因為數(shù)據(jù)都在索引了,不存在回表的概念了。
--具體的操作記錄后續(xù)更新...
小結:合理的使用索引組織表,可以提高效率,節(jié)省空間,但索引組織表也是存在很多限制的,特別是oracle的索引組織表,因為沒有實在的物理rowid,只存在邏輯rowid,在索引組織表上再建索引需要額外的考慮。
推薦看看下面的資料
oracle編程藝術 http://blog.csdn.net/knowhow/archive/2008/01/13/2042277.aspx 表 索引章節(jié)
楊老大的 索引組織表中邏輯ROWID的物理猜 http://yangtingkun./post/468/503568