Oracle ALTER TABLE MOVE INCLUDING ROWS无法正常工作

8ehkhllq  于 2023-08-03  发布在  Oracle
关注(0)|答案(1)|浏览(114)

我尝试使用ALTER TABLE MOVE...INCLUDING ROWS作为faster alternativeDELETE,但在以下情况下无法正常工作:
1.存在索引,并且
1.筛选条件导致空表
下面是一个例子:

create table t (
    c1 int not null
);

create index t_index on t(c1);

insert into t values ( 1 );
insert into t values ( 2 );

alter table t move including rows where c1 > 2 update indexes;

字符串
这将导致一个空表,但:

select * from t;


| C1 |
| ------------ |
| 1 |
| 2 |
这是B/c,它使用t_index,如查询计划所示:

----------------------------------------------------------------------------
| 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数据库19 c企业版19.0.0.0.0 -生产。这是一个已知的bug,还是我误解了Oracle应该如何工作?

z31licg0

z31licg01#

是的,这是一个bug。我可以复制到19.18晚(我没有任何更近的)。请注意,当您有一个没有索引的附加列时会发生什么:

create table t (
    c1 int not null,
    c2 int not null
);

create index t_index on t(c1);

insert into t values ( 1,1 );
insert into t values ( 2,1 );

alter table t move including rows where c1 > 2 update indexes;

select /*+ index(t) */ * from t;

字符串
测试结果:

ORA-08103: object no longer exists


它使用了索引(因为我暗示它这样做,否则它不会这样做),并且因为它需要从索引中没有的表段中获取一列,它开始从索引中存储的ROWID计算表块地址,但是ROWID引用了一个不存在的段(旧的pre-move表),所以抛出了这个错误。这证明在ALTER TABLE MOVE INCLUDING ROWS匹配0行的情况下,Oracle绕过了索引维护,但0行也将索引标记为可用,因此您有一个 usable 索引,其中包含旧的无效ROWID s。绝对是个bug
您的测试显示了一个不同的答案,而不是当索引被 * 独占 * 使用时出错。因为您没有引用索引中没有的任何列,所以它实际上根本不会访问表(这就是为什么您不必提示它使用索引,它认为这是一个优势,并选择它作为最佳路径)。因此,您的查询从索引本身获得了所需的一切,但索引中的数据是坏的,因为它没有在应该重建的时候重建。它不会出错,因为它从不尝试使用ROWID,因为它不需要访问表段。但这只是同一个问题的另一个症状:指向不存在的段的未重建索引。显然,update indexes不会发生。
请在Oracle支持下对此创建SR,当结果根据优化器选择的执行路径发生变化时,这肯定是一个错误。如果你没有一个MOS帐户,让我知道,我会为你做的。一个快速的bug搜索没有找到任何明显的匹配,所以它可能是没有人报告过的东西。

相关问题