利用SQL执行计划设计特性改变IoT表类型句的妙招(⑬)执行计划详解
梁敬彬梁敬弘兄弟出品
往期回顾
左右SQL执行计划妙招 ①——子查询的应用范围
左右SQL执行计划妙招 ②——Hint无效原因
左右SQL执行计划妙招 ③——执行计划SQL写法差异改变【with子句】
左右SQL执行计划妙招 ④——执行计划SQL写法差异改变【insert all】
左右SQL执行计划妙招 ⑤——执行计划利用设计特性改变【并行度影响】
左右SQL执行计划妙招 ⑥——执行计划SQL写法差异改变【rownum分页】
左右SQL执行计划妙招 ⑦——执行计划SQL写法差异改变【rownum实体化】
左右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
核心差异分析
执行计划对比
观察两个执行计划的关键差异:

IOT表的技术原理
IOT表实现了"表即索引,索引即表"的设计理念,数据直接存储在B树索引的叶子节点中,从根本上消除了回表操作。
应用场景与性能考虑
适用场景
性能特征
总结
IOT表通过消除回表操作,在主键访问场景下能够显著提升查询性能。从本例可以看出,IOT表将逻辑读从3次减少到2次,在大数据量环境下这种优势更加明显。选择IOT表需要综合考虑业务查询模式和数据特征,在合适的场景下能够实现显著的性能优化效果。

未完待续…
左右SQL执行计划妙招 ⑭ ——执行计划利用设计特性改变【物化视图影响】
系列回顾
“大白话人工智能” 系列
“数据库拍案惊奇” 系列
“世事洞明皆学问” 系列
作者:收获不止数据库