索引組織表(index organized table ,IOT)
索引組織表(index organized table ,IOT)
默認情況下所有的表都是堆組織表,對表中的記錄不進行排序。堆組織表通過rowid 來訪問(定位)表中的記錄。IOT 使用b-tree index 的結構存儲記錄。邏輯上按照主鍵排序,和正常的主鍵索引不同的是,主鍵索引僅僅是存儲定義列的值。IOT index 存儲所有IOT表中所有的列,并按照主鍵排序。索引和表合二為一,存儲在同一個數據庫對象中。表中記錄的訪問也不是通過傳統的rowid來現實,而是通過主鍵來訪問。
創建IOT
IOT中需要存在主鍵,并且在創建IOT的語句中使用organization index 子句。
創建一個堆組織表,并且給定主鍵約束的名稱方便后面的查找和標識。
SQL> create table test_iot
2 ( id number(3),name varchar2(12),
3 constraints test_iot_id#_pk primary key (id))
4 organization index;
Table created.
查看剛才創建的IOT中的索引。
SQL> select index_name,index_type,table_name,table_type
2 from user_indexes
3 where table_name = 'TEST_IOT';
INDEX_NAME INDEX_TYPE TABLE_NAME TABLE_TYPE
--------------- --------------- --------------- -----------
TEST_IOT_ID#_PK IOT - TOP TEST_IOT TABLE
堆組織表中的索引與主鍵的約束同名。下面這個查詢進一步說明堆組織表中索引所在的列。
SQL> select index_name,table_name,column_name
2 from user_ind_columns
3 where table_name = 'TEST_IOT';
INDEX_NAME TABLE_NAME COLUMN_NAME
--------------- --------------- --------------------
TEST_IOT_ID#_PK TEST_IOT ID
查看因為創建堆組織表產生的數據庫對象。
QL> select object_id,object_name,object_type
2 from user_objects
3 order by object_id desc;
OBJECT_ID OBJECT_NAME OBJECT_TYPE
---------- ------------------------- -------------------
69350 TEST_IOT_ID#_PK INDEX
69349 TEST_IOT TABLE
查看數據庫分配給堆組織表的segment。如果我們給主鍵約束起了名字
那么堆組織表的segment name 和主鍵約束的名稱相同,否則會使用
系統默認的段名 SYS_IOT_TOP_<object_id>
SQL> select segment_name,segment_type
2 from user_segments
3 where segment_name like 'T%';
SEGMENT_NAME SEGMENT_TYPE
------------------------- ------------------
TEST_IOT_ID#_PK INDEX
堆組織表是沒有 table segment 的。
IOT 的優勢
在SQL語句的查詢條件中經常需要使用到表中的主鍵這種情況下使用IOT可以實現更好的性能更快的訪問速度。另外索引和表合二為一,只用一個segment 并且不需要存儲rowid,只存儲一遍primary key values 所有可以節省存儲開銷。
關于overflow area
如果在堆組織表中的一些列是不經常訪問的,或者記錄很長應該考慮使用overflow area.把這部分不常用的數據存放在overflow segment 中。可以使用index segment 比較小,從而在檢索index segment 中的數據時性能更好。注:primary key values 總是存儲在index segment中的,no-key values 可以存儲在index segment 中也可以存儲在overflow segment 中。index segment 中的row通過rowid 來連接到overflow segment 中的row.所以select 與DML語句不能直接的訪問overflow 中的數據。overflow segment 的類型是table not index.
創建帶overflow area 的IOT
首先來認識兩個很重要的overflow 子句:
overflow pctthreshold 子句 : 指定index block 中保留的空間的百分比。該百分比需要設置的合理,以便能夠有足夠的空間來存放primary key values.其他的列,如果存儲在index block 中操作了指定的閥值,將不會存儲在index block 中,而是存儲在overflow segment 中。語法格式是:
pctthreshold threshold
threshold in(1...50),默認值是50.
overflow including 子句:指定那些列應該存儲在index block 中。
語法格式是:
including column_name
這里的column_name 可以是最后一個primary key 列,也可以是no primary key 列。
創建一個帶overflow area 的堆組織表,其中id,first_name,last_name 存放在index block 中,其他的列存放在overflow segment 的block中。
SQL> create table test_iot_info
2 ( id number (5),
3 first_name varchar2 (20),
4 last_name varchar2 (20),
5 major varchar2 (30),
6 current_credits number(3),
7 grade varchar2(2),
8 constraints test_iot_info_id#_pk primary key (id))
9 organization index
10 overflow including last_name;
Table created.
查看剛才新建的IOT的索引信息
SQL> select index_name,index_type,table_name
2 from user_indexes
3 where table_name = 'TEST_IOT_INFO';
INDEX_NAME INDEX_TYPE TABLE_NAME
--------------- --------------- ------------------------------
TEST_IOT_INFO_ID#_PK IOT - TOP TEST_IOT_INFO
SQL> select index_name,table_name,column_name
2 from user_ind_columns
3 where table_name = 'TEST_IOT_INFO';
INDEX_NAME TABLE_NAME COLUMN_NAME
--------------- ------------------------------ ---------------
TEST_IOT_INFO_ID#_PK TEST_IOT_INFO ID
查看由創建IOT 所生成的對象,這里因為使用了overflow 所以
多出了一個 SYS_IOT_OVER_69353. overflow 的命名格式是
SYS_IOT_OVER_<table object_id>.
SQL> select object_id,object_name,object_type
2 from user_objects
3 order by object_id desc;
OBJECT_ID OBJECT_NAME OBJECT_TYPE
---------- ------------------------------ -------------------
69355 TEST_IOT_INFO_ID#_PK INDEX
69354 SYS_IOT_OVER_69353 TABLE
69353 TEST_IOT_INFO TABLE
查看由創建IOT 表生成的segment。
SQL> select segment_name,segment_type
2 from user_segments
3 order by segment_name;
SEGMENT_NAME SEGMENT_TYPE
------------------------- ------------------
TEST_IOT_INFO_ID#_PK INDEX
注意 IOT 表的overflow segment name 與 對象名相同。