Oracle使用Online子句建立索引報錯ORA-01450: maximum key length (3215) exceeded
阿新 • • 發佈:2022-01-17
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操作。