1. 程式人生 > 其它 >Oracle使用Online子句建立索引報錯ORA-01450: maximum key length (3215) exceeded

Oracle使用Online子句建立索引報錯ORA-01450: maximum key length (3215) exceeded

Oracle使用Online子句建立索引報錯ORA-01450: maximum key length (3215) exceeded

版本:11.2.0.4.0

生產有一張表使用online方式建立索引的時候報錯,如下:

SQL> create index idx_name on test(name) online;
create index idx_name on test(name) online
                         *
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA
-01450: maximum key length (3215) exceeded

如果不使用online子句建立則正常。

這種一般來說需要藉助10046功能,由於11g預設有個10046 trace檔案無法顯示完整create table的bug,需要先打上補丁18705302。

詳見:Oracle Trace檔案的建立表(create table)語句顯示不完整

實際Oracle Trace檔案的建立表(create table)語句顯示不完整這篇文章示例語句正是以online建立索引為例子的。

可以看出,create index ... online會內部會建立臨時的索引組織表。

(PS:當然表不能是空段,也就是延遲段建立剛建立的沒有資料的新表,不然即使是online也不會有IOT表產生)。

結合報錯ORA-01450: maximum key length (3215) exceeded一開始還以為是儲存的欄位內容不能超過3215長度,實際上不是這樣。

報錯重現

建立測試表

由於使用了延遲段建立,即使online也不會報錯。

SQL> create table test ( name varchar2(4000));

Table created.

SQL> select * from user_segments where segment_name='TEST';

no rows selected

SQL> create index idx_test on test (name) online;

Index created. SQL> drop index idx_test; Index dropped.

插入資料申請表段,回滾,online建立索引。

可以看出即使沒有資料,在存在表段的前提下online建立索引也會報錯ORA-01450。

SQL> insert into test values ('a');

1 row created.

SQL> rollback;

Rollback complete.

SQL> select count(*) from test;

  COUNT(*)
----------
         0

SQL> select count(*) from user_segments where segment_name='TEST';

  COUNT(*)
----------
         1

SQL> create index idx_test on test (name) online;
create index idx_test on test (name) online
                         *
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01450: maximum key length (3215) exceeded

開啟10046,重新online建立索引。

SQL> select value from v$diag_info where name like '%De%';

VALUE
--------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/zkm/zkm/trace/zkm_ora_2867.trc

SQL> alter session set events '10046 trace name context forever,level 12';

Session altered.

SQL> create index idx_test on test (name) online;
create index idx_test on test (name) online
                         *
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01450: maximum key length (3215) exceeded


SQL> alter session set events '10046 trace name context off';

Session altered.

檢視10046,可以看到建立IOT表的語句:

create table "ZKM"."SYS_JOURNAL_87429" (C0 VARCHAR2(4000),  opcode char(1), partno number,  rid rowid, primary key( C0 , rid )) organization index TABLESPACE "USERS"

實際上,經過測試可以發現,IOT表的欄位長度不能超過3212。

SQL> create table iot_test ( name varchar2(3213),primary key(name)) organization index;
create table iot_test ( name varchar2(3213),primary key(name)) organization index
*
ERROR at line 1:
ORA-01450: maximum key length (3215) exceeded


SQL> create table iot_test ( name varchar2(3212),primary key(name)) organization index;

Table created.

由於IOT表的這種限制,如果表字段本身定義的長度超過3212,則無法使用online子句建立索引。

這種情況下,只能去掉online了。去掉online的話需要注意建立索引期間會阻塞DML操作。