os: centos 7.4
db: oracle 11.2.0.4
索引组织表 IOT 全称是 Index-Organized Tables,访问方式和 oracle 的 heap 表一样,但是物理存储类似 btree 索引。
通常情况下,索引组织表的主键是由表中多个列组成。
索引组织表的数据是按照主键的顺序存储的,所以必须有主键,另外索引组织表没有数据段,所以没有物理ROWID值。
索引组织表并不适合广泛使用,可以用如下指导原则评估某个表是否适合被创建成索引组织表。
- 列数较少
- 由一个符合主键(表中的几列)组成
- 需要快速的主键访问
顺带提下: mysql 的默认存储存储 innodb 就是使用 iot 方式。
版本
# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core)
#
# su - oracle
Last login: Tue Jan 21 03:40:05 CST 2020 on pts/0
$ sqlplus / as sysdba;
SQL*Plus: Release 11.2.0.4.0 Production on Mon Feb 3 10:29:09 2020
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SQL> set lines 300;
SQL> set pages 300;
SQL>
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
SQL>
iot
iot表必须有主键,否则建表报错
SQL> create table iot_t0 (
c0 varchar2(100),
c1 varchar2(100),
c2 varchar2(100),
c3 varchar2(100)
)
organization index
;
ERROR at line 7:
ORA-25175: no PRIMARY KEY constraint found
SQL> create table iot_t0 (
c0 varchar2(100),
c1 varchar2(100),
c2 varchar2(100),
c3 varchar2(100),
constraint pk_iot_t0 primary key (c0)
)
organization index
;
SQL> select to_char(dbms_metadata.get_ddl('TABLE','IOT_T0')) from dual;
TO_CHAR(DBMS_METADATA.GET_DDL('TABLE','IOT_T0'))
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE TABLE "SCOTT"."IOT_T0"
( "C0" VARCHAR2(100),
"C1" VARCHAR2(100),
"C2" VARCHAR2(100),
"C3" VARCHAR2(100),
CONSTRAINT "PK_IOT_T0" PRIMARY KEY ("C0") ENABLE
) ORGANIZATION INDEX NOCOMPRESS PCTFREE 10 INITRANS 2 MAXTRANS 255 LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSTEM"
PCTTHRESHOLD 50
查看下执行计划
SQL> insert into iot_t0
select level, dbms_random.string('a',100),dbms_random.string('a',100),dbms_random.string('a',100) from dual connect by level <=10000;
SQL>
SQL> set autotrace traceonly;
SQL>
SQL> select * from iot_t0 where c0='9998';
Execution Plan
----------------------------------------------------------
Plan hash value: 2900192463
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 208 | 1 (0)| 00:00:01 |
|* 1 | INDEX UNIQUE SCAN| PK_IOT_T0 | 1 | 208 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("C0"='9998')
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
1017 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
SQL> set autotrace off;
SQL> select table_name,iot_name,iot_type from user_tables where table_name='IOT_T0';
TABLE_NAME IOT_NAME IOT_TYPE
------------------------------ ------------------------------ ------------
IOT_T0 IOT
SQL> select index_name,index_type from user_indexes ui where 1=1 and table_name='IOT_T0';
INDEX_NAME INDEX_TYPE
------------------------------ ---------------------------
PK_IOT_T0 IOT - TOP
SQL> select segment_name,segment_type,bytes from user_segments us where us.segment_name in ('IOT_T0','PK_IOT_T0');
SEGMENT_NAME SEGMENT_TYPE BYTES
--------------------------------------------------------------------------------- ------------------ ----------
PK_IOT_T0 INDEX 5242880
可以看出表 IOT_T0 在 user_segments 并没有查询到。
参考: