往期回顾:
左右SQL执行计划妙招 ③ ——执行计划SQL写法差异改变【with子句】
左右SQL执行计划妙招 ④ ——执行计划SQL写法差异改变【insert all】
左右SQL执行计划妙招 ⑤ ——执行计划利用设计特性改变【并行度影响】
左右SQL执行计划妙招 ⑥ ——执行计划SQL写法差异改变【rownum分页】
左右SQL执行计划妙招 ⑦——执行计划SQL写法差异改变【rownum实体化】
左右SQL执行计划妙招 ⑧ ——执行计划SQL写法差异改变【rowid 的影响】
左右SQL执行计划妙招 ⑧ ——执行计划SQL写法差异改变【rowid 的影响】
左右SQL执行计划妙招 ⑨ ——执行计划SQL写法差异改变【缓存结果影响】
左右SQL执行计划妙招 ⑩ ——执行计划SQL写法差异改变【分区条件有无】
左右SQL执行计划妙招⑪ ——执行计划利用设计特性改变【分区设计影响】
左右SQL执行计划妙招 ⑫ ——执行计划利用设计特性改变【Cluster类型】
索引组织表(Index-Organized Table,IOT)是Oracle特有的表结构,通过将表数据直接存储在索引结构中,从根本上消除了回表操作。本文通过对比实验,展示IOT表在执行计划和性能方面的独特优势。
创建结构相同的普通表和IOT表进行性能对比:
set autotrace off -- 创建普通堆表 create table heap_addresses ( empno number(10), addr_type varchar2(10), street varchar2(10), city varchar2(10), state varchar2(2), zip number, primary key (empno) ); -- 创建索引组织表 create table iot_addresses ( empno number(10), addr_type varchar2(10), street varchar2(10), city varchar2(10), state varchar2(2), zip number, primary key (empno) ) organization index; -- 插入相同的测试数据 insert into heap_addresses select object_id,'WORK','123street','washington','DC',20123 from all_objects; insert into iot_addresses select object_id,'WORK','123street','washington','DC',20123 from all_objects; commit;
对比实验:回表操作的性能差异
语句1:普通表的主键查询
set linesize 1000 set autotrace traceonly select * from heap_addresses where empno=22;
执行计划:
-------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 50 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | HEAP_ADDRESSES | 1 | 50 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | SYS_C0013751 | 1 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- 统计信息 -------------------------------------------------------------------------------------------- 0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 659 bytes sent via SQL*Net to client 405 bytes received via SQL*Net from client 1 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
语句2:IOT表的主键查询
select * from iot_addresses where empno=22; 执行计划: ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 50 | 1 (0)| 00:00:01 | |* 1 | INDEX UNIQUE SCAN | SYS_IOT_TOP_104441 | 1 | 50 | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------- 统计信息 ----------------------------------------------------------------------------------------- 0 recursive calls 0 db block gets 2 consistent gets 0 physical reads 0 redo size 751 bytes sent via SQL*Net to client 416 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
执行计划对比
观察两个执行计划的关键差异:

- 普通表访问路径: 索引扫描获取ROWID → 根据ROWID回表获取数据(两次IO)
- IOT表访问路径: 直接在索引结构中获取完整数据(一次IO)
IOT表实现了"表即索引,索引即表"的设计理念,数据直接存储在B树索引的叶子节点中,从根本上消除了回表操作。
适用场景
- 主键访问频繁:大部分查询通过主键进行
- 读多写少:查询操作远多于DML操作
- 数据量适中:避免索引结构过于复杂
性能特征
- 优势: 减少IO次数、提高缓存效率、优化存储空间
- 限制: DML操作相对较慢、非主键查询需要二级索引支持
IOT表通过消除回表操作,在主键访问场景下能够显著提升查询性能。从本例可以看出,IOT表将逻辑读从3次减少到2次,在大数据量环境下这种优势更加明显。选择IOT表需要综合考虑业务查询模式和数据特征,在合适的场景下能够实现显著的性能优化效果。

未完待续..
左右SQL执行计划妙招 ⑭ ——执行计划利用设计特性改变【物化视图影响】
公众号:收获不止数据库
微信:ljbyxl1213
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9091385/viewspace-3086451/ ,如需转载,请注明出处,否则将追究法律责任。