OS:SUN OS 5.9
DB: 9.2.0.7
一、问题出现的过程
为了降低T1表的高水位,解决数据库负载过高的问题,执行如下操作:
-- 移动表降低高水位
alter table T1 move;
-- 在线重建该表的索引
alter index IDX_SUBMIT_SELECT1 rebuild online;
alter index IDX_SUBMIT_SELECT2 rebuild online;
alter index INDEX_BI rebuild online;
alter index MSG_ID_INDEX rebuild online;
alter index SUBMIT_PHONENUMBER rebuild online;
alter index SYS_C008357 rebuild online;
-- 为使用CBO收集该表的统计信息
exec dbms_stats.gather_table_stats('GEGW','T1', degree => 4,cascade => true, ESTIMATE_PERCENT => null);
在执行到alter index SUBMIT_PHONENUMBER rebuild online;句时出现ORA-01450错误:
ORA-01450: maximum key length (3215) exceeded
此时这个索引处于不稳定状态,对T1表的增删改等DML操作都会报以下错误:
ORA-01502: index "U1"."SUBMIT_PHONENUMBER" or partition of such index is in unusable state
二、分析
online rebuild 索引的时候,oracle用来记录改变的日志表是个IOT,而对于IOT一个index key的总长度只能达到block size的40%左右(此库的db_block_size=8K)。
查询问题索引的列信息:
select TABLE_NAME,COLUMN_NAME,COLUMN_LENGTH,CHAR_LENGTH from user_ind_columns where INDEX_NAME='SUBMIT_PHONENUMBER';
TABLE_NAME COLUMN_NAME COLUMN_LENGTH CHAR_LENGTH
------------------------------ -------------------- ------------- -----------
T1 DEST_TERMINAL_ID 3300 3300
显示该索引引用了一个DEST_TERMINAL_ID VARCHAR2(3300)的字段,超过了3215的限制,所以出现了上面的ORA-01450错误
三、问题解决
基于上面的分析,解决方法就是去掉online
alter index SUBMIT_PHONENUMBER rebuild;
exec dbms_stats.gather_table_stats('GEGW','T1', degree => 4,cascade => true, ESTIMATE_PERCENT => null);
执行成功,后面对表T1的DML可以正常执行,用exec show_space('T1','TABLE','U1');查看该表的高水位,约降低了3/4.
四、结论
1. 建议不要在超过3215字节(db_block_size=8K时)的列上建索引
2. 如果违反上面一条,则不能在执行create index、alter index rebuild时加online选项,但这样做会在命令执行期间对表锁定,这中间的记录修改都将等待索引操作的结束,一定程度上影响了高可用性。
--转自