【赵渝强老师】Oracle的行地址:ROWID

ROWID 是 Oracle 数据库伪列(pseudocolumn) ,每一行数据都拥有一个ROWID,但它并不是表中真实存储的字段;它代表该行在磁盘上的物理存储地址,可以快速定位一行记录。

伪列使用:可以select rowid from table;查询,不能insert/update给rowid赋值。

视频讲解如下
【赵渝强老师】Oracle的行地址:ROWID

1. ROWID 格式(物理ROWID,10g及以后扩展ROWID)

Oracle 扩展ROWID一共18位字符 ,由64进制字符组成(A‑Z,a‑z,0‑9,+,/)。

格式:

复制代码
OOOOOOFFFBBBBBBRRR
对象号|文件号|块号 |行号
片段 长度 含义
OOOOOO 6位 数据对象编号(Data Object Number),标识段(表/索引等)
FFF 3位 相对文件号(Relative File Number),表空间内的数据文件编号
BBBBBB 6位 数据块号(Block Number),该文件内的数据块编号
RRR 3位 块内行号(Row Number),数据块内部,行的槽位号(从0开始)

示例:

sql 复制代码
SQL> SELECT ROWID, empno, ename, sal FROM emp WHERE empno=7839;

# 输出的信息如下:
ROWID			EMPNO ENAME	   SAL
------------------ ---------- ---------- -----
AAAR4WAAHAAAAFuAAI	 7839 KING	  5000

拆解:

  • AAAR4W:对象ID
  • AAH:相对文件号
  • AAAAFu:块号
  • AAI:块内行号

⚠️ 注意:64进制,不是16进制,不能直接当成数字阅读,Oracle内部会做转换。

2. ROWID 的重要特点

  1. 定位速度极快
    ROWID直接携带磁盘物理地址。Oracle通过ROWID访问行,不需要索引扫描,是访问单行最快方式。
sql 复制代码
-- 通过rowid直接查询,效率极高
SQL> select * from emp where rowid='AAAR4WAAHAAAAFuAAI';

# 输出的信息如下:
  EMPNO ENAME      JOB	       MGR HIREDATE    SAL  COMM     DEPTNO
------- ---------- --------- ---------- --------- ----- ----- ----------
   7839 KING       PRESIDENT 	   17-NOV-81  5000		 10
  1. ROWID什么时候会变化?
  • DELETE + INSERT:旧行删除,插入新行 → ROWID改变
  • UPDATE:普通update不改rowid ;但如果更新导致行迁移(row migration)、行链接(row chaining),行移动到别的块,ROWID不变!只是指针指向新位置
  • ALTER TABLE ... MOVE 表迁移、表收缩shrink、exp/imp导入导出、分区表move分区:ROWID会发生改变

❗重点:UPDATE不会改变ROWID;MOVE、shrink会改变ROWID。

  1. ROWID不是永久不变!不要作为业务主键使用
    很多人踩坑:把ROWID存到业务表当外键。当表发生move/shrink,ROWID全部变化,关联直接失效。

✔适用:临时定位数据;❌禁止做业务主键、业务外键。

  1. 区分 ROWID / UROWID
  • ROWID:普通堆表物理行地址;
  • UROWID:索引组织表(IOT)使用,是逻辑ROWID,不是物理磁盘地址。

3. 相关内置函数

3.1 dbms_rowid 包解析ROWID

sql 复制代码
SQL> SELECT
       ROWID,
       dbms_rowid.rowid_object(ROWID)  对象号,
       dbms_rowid.rowid_relative_fno(ROWID) 相对文件号,
       dbms_rowid.rowid_block_number(ROWID) 块号,
       dbms_rowid.rowid_row_number(ROWID) 块内行号
     FROM emp;

# 输出的信息如下:
ROWID		         对象号        相对文件号      块号       块内行号
------------------ ---------- --------------- ---------- ------------
AAAR4WAAHAAAAFuAAA	73238		    7	        366          0
AAAR4WAAHAAAAFuAAB	73238		    7	        366          1
AAAR4WAAHAAAAFuAAC	73238		    7	        366          2
AAAR4WAAHAAAAFuAAD	73238		    7	        366          3
AAAR4WAAHAAAAFuAAE	73238		    7	        366          4
AAAR4WAAHAAAAFuAAF	73238		    7	        366          5
AAAR4WAAHAAAAFuAAG	73238		    7	        366          6
AAAR4WAAHAAAAFuAAH	73238		    7	        366          7
AAAR4WAAHAAAAFuAAI	73238		    7	        366          8
AAAR4WAAHAAAAFuAAJ	73238		    7	        366          9
AAAR4WAAHAAAAFuAAK	73238		    7	        366         10
AAAR4WAAHAAAAFuAAL	73238		    7	        366         11
AAAR4WAAHAAAAFuAAM	73238		    7	        366         12
AAAR4WAAHAAAAFuAAN	73238		    7	        366         13

14 rows selected.
函数 功能
dbms_rowid.rowid_object(rowid) 获取数据对象ID
dbms_rowid.rowid_relative_fno(rowid) 获取相对文件号
dbms_rowid.rowid_block_number(rowid) 获取数据块号
dbms_rowid.rowid_row_number(rowid) 获取块内行槽号

3.2 根据编号反向生成ROWID

sql 复制代码
--根据给定参数返回一个rowid ,例如
SQL> select dbms_rowid.rowid_create(0,9999,12,1000,13) from dual;

# 输出的信息如下:
DBMS_ROWID.ROWID_C
------------------
000003E8.000D.000C

4. ROWID常见使用场景

  1. DML错误数据快速定位
    导出rowid,快速定位坏数据,用于删除、修正脏数据:
sql 复制代码
delete from emp where rowid='AAAR4WAAHAAAAFuAAI';
  1. 大表更新:通过rowid批量处理,避免全表锁
sql 复制代码
-- 游标循环,根据rowid更新,分批提交
update emp set ename='xxx' where rowid=:rid;
  1. 排查行迁移、行链接问题
    结合dbms_rowid拿到block、file,dump数据块查看存储。

5. 与 openGauss / MySQL 的对比

  • Oracle:ROWID伪列,物理地址;
  • MySQL InnoDB:没有rowid伪列 ,用聚簇索引主键定位行;隐藏列DB_ROW_ID仅当表无主键时内部使用;
  • openGauss(PG):伪列 ctid,格式 (块号,槽号),作用类似Oracle ROWID。

openGauss ctid示例:(0,1),代表第0号块,第1号槽位。ctid也会VACUUM、update时发生变化,不能做业务主键。

6. 经典易错点总结

  1. ROWID是伪列,表定义看不到;
  2. update不会修改ROWID,alter table move / shrink space 会修改ROWID;
  3. 绝对不要把ROWID存储为业务字段;
  4. IOT索引组织表,要用UROWID,普通ROWID无意义;
  5. ROWID是64进制,不是16进制。
相关推荐
c_hn_00714 小时前
量化数据12:国内期货L2历史数据:Tick、逐笔、五档盘口一次性打包下载
数据库·1024程序员节·#深度订单簿数据·#历史行情订单薄·#本地csv数据存储
GeW14 小时前
从"补短板"到"强优势"Linux与数据库认证成为产业跃迁人才支点
linux·数据库
数据库小学妹14 小时前
MySQL NULL陷阱:NOT IN、三值逻辑与NOT EXISTS
数据库·后端·mysql
SelectDB14 小时前
Doris 异步物化视图实战:与 Snowflake MV / Dynamic Tables 分层建模对照
大数据·数据库·云原生
枫昕柚14 小时前
MySQL 建库命令详解:从 CREATE DATABASE 到create table
数据库·mysql
张张123y15 小时前
后端第十六课:Multi-Agent 多智能体(让多个 Agent 分工协作)
大数据·数据库·人工智能·python·deepseek·dsh·agent 框架
todoitbo15 小时前
MongoDB迁移之后,Spring Data 和 Hibernate 各自接哪类请求
大数据·数据库·mongodb·spring·hibernate·金仓数据库
HEJOO915 小时前
数据库日期类型字段如何选型:跨数据库兼容的实践指南
数据库
这个DBA有点耶16 小时前
主库秒级,从库延迟2小时:深挖Online DDL回放的MDL阻塞与算法降级机制
数据库·sql·dba
xcLeigh16 小时前
KingbaseES数据库教程:初识数据库,从安装到跑通第一条SQL
android·数据库·sql·安装·数据库教程·kes