今天在 Oracle 上更新数据的时候,报了如下错误:
ORA-14402: updating partition key column would cause a partition change
意思是:更新分区关键字列将导致分区的更改。
然后百度大法,了解到:
1、默认情况下,Oracle 的分区表对于分区字段是不允许进行 update 操作的,如果有对分区字段行进 update,就会报错 ORA-14402。
2、解决办法:开启表的行转移功能
alter table XX enable row movement;--修改语句
alter table XX disable row movement;--修改回来的语句
这样在 update 以后,会在老分区删除数据,新分区插入数据。
3、enable row movement 会改变 rowid。
下面三种情况需要开启 row movement
1、 更新 Partition Key
分区表某一行更新时,如果更新的是分区列,并且更新后的列值不属于原来的这个分区,如果开启了这个选项,就会把这行从这个分区中 delete 掉,并加到更 新后所属的分区。相当于一个隐式的 delete+insert,但是不会触发 insert/delete 触发器。如果没有开启这个选项,就会在更新时报错 ORA-14402;
这一操作产生影响的特殊之处在于这是个 DML 操作,是和 online transaction 密切相关。对于这样一个 UPDATE,实际上分为3步:
先从原有分区将数据删除;将原数据转移到新分区上;更新数据。
其影响就在于以下几个方面:
一 个 UPDATE 被分解为 DELET、INSERT、UPDATE 三个操作,增加了性能负担。其中,DELETE 的查询条件与原 UPDATE 的查询条件相 同,新的 UPDATE 的查询条件是基于 INSERT 生成的新的 ROWID,相应的Redo Log、Undo Log 会增加;
如果 Update 语句还涉及到了 Local Index 的字段的话,新、旧2个分区上的 Local Index 都要被更新。
还有一点,Row Movement 会和域索引(Domain Index)产生冲突:如果表上定义了域索引,开启 Row Movement 就会失败;反之亦然。
2、 Flaskback table to 某时间
Flashback Table 实际是通过Flashback Query将表中数据进行了一次删除、插入操作,因此ROWID会发生变化。
3、 Shrink Segment
Shrink Segment能帮助我们压缩数据段、整理数据碎片、降低高水位,以提高性能、节省空间。
有必要说明一下,row movement 并不是行迁移,最大的区别是行迁移的 rowid 是不变的
,行迁移是 update 行记录时,数据块没有足够的空闲容纳数据行,Oracle 将此行移到其他数据块,同时保留此行的rowid不变,并在原数据块建一指针指向新的行位置。这 种情况下,读取一行数据就会访问2个数据块,增加 IO,导致性能下降。
如果直接创建主键,使用的global index,当某分区被 drop 后,主键会失效
ALTER TABLE PHAECDA1.HCPSGLSINFOPZOW_NEW ADD CONSTRAINT PK_STAMP PRIMARY KEY(T_STAMP) tablespace xx;
改为 local index,但不包含分区段,报错:
ALTER TABLE PHAECDA1.HCPSGLSINFOPZOW_NEW ADD CONSTRAINT PK_STAMP PRIMARY KEY(T_STAMP) using index local tablespace xxx;
ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE
ORA-14039: 分区列必须构成 UNIQUE 索引的关键字列子集。
Local index ,主键+分区键 作为新的主键,自动创建分区 index,index 会按分区段 Partition 分区到 table 的分区表空间
ALTER TABLE PHAECDA1.HCPSGLSINFOPZOW_NEW ADD CONSTRAINT PK_STAMP PRIMARY KEY(T_STAMP,CLDATE) USING INDEX LOCAL;
先创建 index,再创建主键,当然,主键也可直接作为分区段。
参考文章:
https://www.cnblogs.com/apple2016/p/5682298.html