【赵渝强老师】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进制。
相关推荐
重生之高冷汉堡包1 小时前
什么是数据中心代理?原理拆解、类型区别、应用场景与选型指南
服务器·网络·数据库·安全·ip
Mortalbreeze1 小时前
MySQL 基础篇(八):复合查询之多表查询、内外连接、子查询
数据库·mysql
Xxtaoaooo1 小时前
NocoDB在线表格数据库:fnOS部署、MySQL可视化与远程协作实操
数据库·mysql·docker·cpolar·nocodb
张继雁1 小时前
30~50MPa数控高压清洗:前端分级过滤逻辑,抑制硬质磨粒对喷嘴冲蚀
大数据·数据库·人工智能·机器学习·创业创新
言乐61 小时前
PythonLOLM自动生成复盘报告模型
开发语言·前端·数据库·人工智能·python
倔强的石头_1 小时前
从 KStudio 到 KSQL Developer:国产数据库的 SQL 编辑器,已经卷到这个程度了
数据库
JavaEdge.1 小时前
设定索引方法和检索设置
数据库
小蒜学长1 小时前
基于Vue.js + Spring Boot的酒店客房预订系统设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·酒店客房预订系统
墨者阳1 小时前
KingbaseES V9R2C16 深度实测:64位事务ID、内存防护、集群备份与坏块修复四大能力全解析
数据库