首页 > Linux操作系统 > Linux操作系统 > 索引创建和重建对键值的限制
简单描述创建和重建索引的过程对索引键值大小的要求。
索引和表的存储结构不同,由于索引要根据索引键值进行排序,因此要求索引的键值必须能够放到一个BLOCK中。所以根据数据块大小的不同,对键值的大小限制也不同。
一般来说建立索引的时候,索引键值的最大值一般在DB_BLOCK_SIZE的3/4左右,看一个DB_BLOCK_SIZE为8K的例子:
SQL> SHOW PARAMETER DB_BLOCK_SIZE
NAME TYPE VALUE
------------------------------------ ----------- ----------------------------
db_block_size integer 8192
SQL> CREATE TABLE T_CHAR
2 (C1 CHAR(2000),
3 C2 CHAR(2000),
4 C3 CHAR(2000),
5 C4 CHAR(2000));
表已创建。
SQL> CREATE INDEX IND_T_CHAR_1 ON T_CHAR(C1, C2, C3);
索引已创建。
SQL> CREATE INDEX IND_T_CHAR_2 ON T_CHAR(C1, C2, C3, C4);
CREATE INDEX IND_T_CHAR_2 ON T_CHAR(C1, C2, C3, C4)
*
第 1 行出现错误:
ORA-01450: 超出最大的关键字长度 (6398)
而这时创建索引的限制,对于ONLINE REBUILD方式,由于Oracle需要在同一个BLOCK中保存至少两个索引键值,因此索引键值的最大限制,只有创建时的一半:
SQL> ALTER INDEX IND_T_CHAR_1 REBUILD ONLINE;
ALTER INDEX IND_T_CHAR_1 REBUILD ONLINE
*
第 1 行出现错误:
ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01450: 超出最大的关键字长度 (3215)
SQL> ALTER INDEX IND_T_CHAR_1 REBUILD;
索引已更改。
可以看到,普通的REBUILD则没有这个限制。
SQL> show parameter db_block_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 16384
SQL> create table t_varchar2
2 (c1 varchar2(4000),
3 c2 varchar2(4000),
4 c3 varchar2(4000),
5 c4 varchar2(4000));
Table created.
SQL> create index ind_t_varchar2_1 on t_varchar2(c1, c2, c3);
Index created.
SQL> create index ind_t_varchar2_2 on t_varchar2(c1, c2, c3, c4);
create index ind_t_varchar2_2 on t_varchar2(c1, c2, c3, c4)
*
ERROR at line 1:
ORA-01450: maximum key length (12958) exceeded
SQL> alter index ind_t_varchar2_1 rebuild online;
alter index ind_t_varchar2_1 rebuild online
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01450: maximum key length (3800) exceeded
这是DB_BLOCK_SIZE为16K的例子,可以看到创建索引的最大键值增加了一倍还多,而ONLINE REBUILD的键值限制却没有多大的增长。
最后看看32K的情况:
SQL> show parameter db_block_size
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
db_block_size integer 32768
SQL> create table t_var
2 (c1 varchar2(4000),
3 c2 varchar2(4000),
4 c3 varchar2(4000),
5 c4 varchar2(4000),
6 c5 varchar2(4000),
7 c6 varchar2(4000),
8 c7 varchar2(4000),
9 c8 varchar2(4000));
表已创建。
SQL> create index ind_t_var_1 on t_var(c1, c2, c3, c4, c5, c6, c7);
create index ind_t_var_1 on t_var(c1, c2, c3, c4, c5, c6, c7)
*
第 1 行出现错误:
ORA-01450: 超出最大的关键字长度 (26054)
SQL> create index ind_t_var_1 on t_var(c1, c2, c3, c4, c5, c6);
索引已创建。
SQL> alter index ind_t_var_1 rebuild online;
alter index ind_t_var_1 rebuild online
*
第 1 行出现错误:
ORA-00604: 递归 SQL 级别 1 出现错误
ORA-01450: 超出最大的关键字长度 (3800)
可以看到,ONLINE REBUILD所允许的最大键值就是3800,而CREATE INDEX所允许的最大键值又增加了一倍。从这一点上看,ONLINE REBUILD的限制还是很严的,如果在VARCHAR2(4000)列上建立索引,则意味着这个索引无法进行ONLINE REBUILD。这也从另一个角度说明,定义列的长度时,应该根据具体的需要,而不是随便就定义成最大值。这样即使字段中存储的值没有那么长,但是由于列的定义长度超过限制,也会使得ONLINE REBUILD的操作无法执行。
而且对于8K的DB_BLOCK_SIZE,ONLINE REBUILD的键值最大为3215,如果DB_BLOCK_SIZE是4K,甚至是2K,则ONLINE REBUILD的键值限制还会缩小1倍或2倍。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-608464/ ,如需转载,请注明出处,否则将追究法律责任。