问题1
在创建索引时出现如下报错:
CREATE INDEX MYINDEX ON TEST (NAME DESC, DESCRIPTION1 DESC,DESCRIPTION2 DESC)
tablespace INDX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
);
说明:
NAME varchar2(50), DESCRIPTION1 varchar2(4000),DESCRIPTION2 varchar2(4000)
原因分析
从字面意义可以看出,01450是由于我们的关键字超出了某些限定值而引起的。oracle不推崇单条索引记录占用较大的存储空间,在9i之前的版本,oracle规定每个数据块至少存放两条完整索引记录,在9i之后条件放宽,每个数据块至少存放一条完整索引记录。毫无疑问,在数据块中除去索引记录本身的数据,还存储了一些辅助信息(大概占用了192个字节),除此之外,每条索引记录还包含了除key值之外的附加信息,如rowid等。因此,,在创建索引时,被索引列的长度是受限制的,大概范围为(blocksize-192)*80%。
所以当block size为8k时,理论上被索引列的长度总和不可以超过 (8192-192)*0.8=6400 。
所以,当索引列为(NAME , DESCRIPTION1,DESCRIPTION2)时,总长度超过最大值,因此会报错。
如果,将索引列改为(NAME , DESCRIPTION1),则可创建成功。
CREATE INDEX MYINDEX ON TEST (NAME DESC, DESCRIPTION1 DESC)
tablespace INDX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
);
问题2
online创建索引时出现如下报错:
CREATE INDEX MYINDEX ON TEST (NAME DESC, DESCRIPTION1 DESC)
tablespace INDX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
) online;
依据上面的错误提示,依然没有定位到原因。
然后多次进行其他尝试后,又出现了如下报错:
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01450: maximum key length (3215) exceeded
这下突然明朗了。
原来是索引列总长度超过最大允许值3215了。但是,问题1中普通建索引时索引列可允许总长度不是6398吗?怎么又变成3215了呢?
原因分析
online创建的过程中会生成一个中间表,用来记录创建过程中的变化,而这个表是IOT表。经测试发现IOT表的限制比较严格,block size为8k时,最大长度只能有3215,所以使用online创建索引时,如果创建索引所需要的字段长度加起来超过3215就会报错。
但是因为普通创建没有这个限制,所以可以创建成功。
处理方式
调整为普通创建
CREATE INDEX MYINDEX ON TEST (NAME DESC, ESCRIPTION DESC)
tablespace INDX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
) ;