左右SQL执行计划妙招 ⑧ ——执行计划SQL写法差异改变【rowid 的影响】

梁敬彬梁敬弘兄弟出品

往期回顾
左右SQL执行计划妙招 ①——子查询的应用范围
左右SQL执行计划妙招 ②——Hint无效原因
左右SQL执行计划妙招 ③——执行计划SQL写法差异改变【with子句】
左右SQL执行计划妙招 ④——执行计划SQL写法差异改变【insert all】
左右SQL执行计划妙招 ⑤——执行计划利用设计特性改变【并行度影响】
左右SQL执行计划妙招 ⑥——执行计划SQL写法差异改变【rownum分页】
左右SQL执行计划妙招 ⑦——执行计划SQL写法差异改变【rownum实体化】

在SQL性能优化过程中,SQL的写法细节常常对执行计划产生不可忽视的影响。合理利用Oracle数据库的特性,能够让同一业务实现方案下的SQL拥有更高的执行效率。本篇将聚焦于rowid的使用,通过两个实际对比例子,详细剖析不同SQL写法对执行计划的影响,为SQL优化实战提供借鉴。

环境准备

首先,构建测试环境并初始化数据:

drop table t purge;
create table t as select * from dba_objects;
update t set object_id = rownum;
commit;
create index idx_object_id on t(object_id);
set autotrace off;
select rowid from t where object_id=8;

此时,可以查到object_id=8的数据行对应的rowid,例如:

ROWID
-----
AAAaq2AALAAApOrAAH

SQL写法与执行计划对比

1. 普通条件更新(语句1)

update t set object_name='abc' where object_id=8;
执行计划:

-----------------------------------------------------------------------------------
Plan hash value: 3890322047
-----------------------------------------------------------------------------------
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT  |               |     1 |    79 |     2   (0)| 00:00:01 |
|   1 |  UPDATE           | T             |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IDX_OBJECT_ID |     1 |    79 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------
   - dynamic sampling used for this statement (level=2)
统计信息:

         30  recursive calls
          2  db block gets
         75  consistent gets
          0  physical reads
        448  redo size
        680  bytes sent via SQL*Net to client
        616  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

该语句的执行计划中,Oracle选择通过idx_object_id索引进行INDEX RANGE SCAN,然后定位数据行并执行更新。

2. 使用rowid精确定位(语句2)

update t set object_name='abc'  where object_id=8 and t.rowid='AAAaq2AALAAApOrAAH';
执行计划:

------------------------------------------------------------------------------------
Plan hash value: 815416494
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT            |      |     1 |    91 |     1   (0)| 00:00:01 |
|   1 |  UPDATE                     | T    |       |       |            |          |
|*  2 |   TABLE ACCESS BY USER ROWID| T    |     1 |    91 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------------------------------------------------
   2 - filter("OBJECT_ID"=8)
统计信息:

          0  recursive calls
          3  db block gets
          1  consistent gets
          0  physical reads
          0  redo size
        682  bytes sent via SQL*Net to client
        650  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

在此语句中,加入了rowid作为查询条件。Oracle直接根据rowid访问对应数据行,执行计划变为TABLE ACCESS BY USER ROWID,这一方式被认为是直接、跳跃式访问表中某条记录的最快途径。

分析

从执行计划及统计信息对比可以看出:
在这里插入图片描述

语句1 先通过索引查找,再定位到表中的记录,适合object_id存在索引的场景。
语句2 由于rowid已明确,无须再借助索引,可以绕过索引查找的步骤,直接到达物理存储位置。Oracle明确选择TABLE ACCESS BY USER ROWID这一最快的单行定位方式,提升了访问效率。
实际应用中,在已知rowid的情况下,采用rowid作为定位依据,可以减少数据库的消耗,实现最短路径访问。在批量或高并发更新场景下,尤其能展现出rowid方式的优势。

使用注意事项

  1. ROWID的时效性
  • DDL操作影响:表重建、分区操作会改变ROWID
  • 数据移动影响:行迁移、行链接可能导致ROWID变化
  • 时间窗口:ROWID应在短时间内使用,避免失效
  1. 业务逻辑考虑
  • 数据一致性:确保ROWID对应的行仍然满足业务条件
  • 并发控制:考虑其他会话可能的数据修改
  • 错误处理:处理ROWID无效的情况
  1. 性能权衡
  • 查询开销:获取ROWID本身也需要成本
  • 应用复杂度:增加了应用逻辑的复杂性
  • 适用范围:并非所有场景都适合使用ROWID

小结

在特定的业务场景下,语句1和语句2在逻辑上完全等价,但性能表现却截然不同。TABLE ACCESS BY USER ROWID是Oracle中最快的访问方式,它通过直接的物理定位避免了索引查找的开销,大幅减少了逻辑读和递归调用。

理解和掌握ROWID的使用技巧,能够在适当场景下显著提升SQL执行效率。然而,ROWID的使用需要谨慎考虑其时效性和业务适用性,在性能优化和代码复杂度之间找到合适的平衡点。

在这里插入图片描述

未完待续…
左右SQL执行计划妙招 ⑨——执行计划SQL写法差异改变【缓存结果影响】

系列回顾

“大白话人工智能” 系列
“数据库拍案惊奇” 系列
“世事洞明皆学问” 系列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

收获不止数据库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值