Oracle 19c中ALTER TABLE MOVE INCLUDING ROWS特定场景失效咨询
使用
ALTER TABLE MOVE...INCLUDING ROWS替代DELETE时的索引异常问题 问题现象
在Oracle 19c Enterprise Edition中,使用ALTER TABLE MOVE...INCLUDING ROWS作为批量删除的高效替代方案时,出现以下不符合预期的情况:
- 当表存在索引,且过滤条件导致移动后表为空时,走索引的查询会返回原有数据,仅强制全表扫描才能得到正确的空表结果。
- 当过滤条件保留部分行时,
UPDATE INDEXES参数能正常维护索引,查询结果符合预期。
复现步骤
-- 创建测试表及索引 create table t ( c1 int not null ); create index t_index on t(c1); -- 插入测试数据 insert into t values ( 1 ); insert into t values ( 2 ); -- 执行MOVE操作,保留c1>2的行(实际无符合条件数据) alter table t move including rows where c1 > 2 update indexes;
异常表现
执行常规查询时,查询计划显示走t_index索引全扫描,返回原有数据:
| C1 |
|---|
| 1 |
| 2 |
对应的查询计划:
---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 | | 1 | INDEX FULL SCAN | T_INDEX | 1 | 13 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------
强制走全表扫描则返回正确的空表结果:
select /*+no_index(t t_index)*/ * from t; --- (none)
正常场景验证
当过滤条件保留部分行时,操作及查询结果均正常:
alter table t move including rows where c1 > 1 update indexes; select * from t;
返回结果:
| C1 |
|---|
| 2 |
问题原因
这是Oracle 19c版本中的已知bug:当ALTER TABLE MOVE...INCLUDING ROWS操作后目标表为空时,UPDATE INDEXES参数未能正确清理索引中的旧数据,导致索引仍保留原表的记录条目。此时查询若选择走索引,就会读取到失效的索引数据,返回错误结果。
临时解决方案
- 执行MOVE操作后,若确认表为空,手动重建索引:
alter index t_index rebuild;
- 临时强制查询走全表扫描(仅用于验证,不建议长期依赖)。
- 升级Oracle到后续补丁集或更高版本(该问题在部分19c补丁包及21c版本中已修复)。
内容的提问来源于stack exchange,提问作者Tianxiang Xiong
相关产品推荐
相关产品推荐

