问题描述
嗨,甲骨文大师团队
我在具有charset AL32UTF8和max_string_size标准的源数据库版本12.1.0.2中有一个架构。
有些表具有列VARCHAR2(2000 CHAR),原则上这可能意味着多达8000个字节,但这里的最大值是4000的,这反映了user_tab_columns中的DATA_LENGTH。
因此,一些具有大量4字节UTF字符的文本可能不适合甚至少于2000个字符,但在实践中,它不是一个普通文本与几个UTF字符的问题。
这些列中有几个被索引,这是没有问题的,因为4000字节的最大限制。
我正在datapump导出此架构并将其导入目标数据库版本19.3中,其中包含charset AL32UTF8和max_string_size扩展。
由于扩展的max_string_size,这些由导入创建的VARCHAR2(2000 CHAR) 列现在具有8000的DATA_LENGTH!
(原则上很好,因为现在没有1942字符串无法容纳的风险;-)
问题是,这些列不能再索引了。
我在datapump导入日志中得到 “ORA-01450: 超过最大密钥长度 (6398)”。
文档指出不可能将max_string_size从扩展更改为标准,因此我无法更改目标数据库。
另外,我真的不想这样做,因为此数据库中的其他模式很可能会从使用Extended中受益。
但是对于这个模式,我希望将这些列的DATA_LENGTH保持足够低 (4000字节),以允许它们被索引。
如果我将列更改为VARCHAR2(4000字节),则允许索引。
但是数据库将允许UTF字符串超过2000个字符,对吗?(只要大多数字符都是1字节的UTF。)
这可能会破坏前端应用程序。
我正在考虑VARCHAR2(4000字节) 与检查约束长度c (col) <= 2000。
您会看到不利的一面吗?
是否有一种在datapump导入期间转换这些列的方法?
还是简单地忽略ORA-01450错误,在导入后更改列,然后创建索引的最佳方法?
还有其他可能有益的想法或提示吗?
谢谢...
啦啦队
/金
我在具有charset AL32UTF8和max_string_size标准的源数据库版本12.1.0.2中有一个架构。
有些表具有列VARCHAR2(2000 CHAR),原则上这可能意味着多达8000个字节,但这里的最大值是4000的,这反映了user_tab_columns中的DATA_LENGTH。
因此,一些具有大量4字节UTF字符的文本可能不适合甚至少于2000个字符,但在实践中,它不是一个普通文本与几个UTF字符的问题。
这些列中有几个被索引,这是没有问题的,因为4000字节的最大限制。
我正在datapump导出此架构并将其导入目标数据库版本19.3中,其中包含charset AL32UTF8和max_string_size扩展。
由于扩展的max_string_size,这些由导入创建的VARCHAR2(2000 CHAR) 列现在具有8000的DATA_LENGTH!
(原则上很好,因为现在没有1942字符串无法容纳的风险;-)
问题是,这些列不能再索引了。
我在datapump导入日志中得到 “ORA-01450: 超过最大密钥长度 (6398)”。
文档指出不可能将max_string_size从扩展更改为标准,因此我无法更改目标数据库。
另外,我真的不想这样做,因为此数据库中的其他模式很可能会从使用Extended中受益。
但是对于这个模式,我希望将这些列的DATA_LENGTH保持足够低 (4000字节),以允许它们被索引。
如果我将列更改为VARCHAR2(4000字节),则允许索引。
但是数据库将允许UTF字符串超过2000个字符,对吗?(只要大多数字符都是1字节的UTF。)
这可能会破坏前端应用程序。
我正在考虑VARCHAR2(4000字节) 与检查约束长度c (col) <= 2000。
您会看到不利的一面吗?
是否有一种在datapump导入期间转换这些列的方法?
还是简单地忽略ORA-01450错误,在导入后更改列,然后创建索引的最佳方法?
还有其他可能有益的想法或提示吗?
谢谢...
啦啦队
/金
专家解答
But the database would then allow UTF strings longer than 2000 characters, right?
是的,确实会:
I'm considering VARCHAR2(4000 BYTE) with a check constraint LENGTHC(col) <= 2000.
Would you see a downside to this?
无法想到任何事情; 由于现有的应用程序已经仅限于2,000个字符,因此不应该出现功能问题。我主要关心的是 “惊喜因素”。也就是说,这是不寻常的事情,所以将来可能会赶上开发人员/dba。
Or is the best way simply to ignore the ORA-01450 errors, alter the columns after the import, and then create the indexes?
这是一个选择;)
您可以通过在索引定义中使用SUBSTR或STANDARD_HASH来解决该问题。优化器可以在不改变查询的情况下使用标准哈希函数进行相等:
您可以在文档中阅读有关此内容的更多信息https://docs.oracle.com/en/database/oracle/oracle-database/20/sqlrf/CREATE-INDEX.html#GUID-1F89BBC0-825F-4215-AF71-7588E31D8BFE
Any other ideas or tips that might be beneficial?
问题是索引键的数据必须小于索引块大小减去一些开销。所以还有另一种解决方法:
将索引放在具有更大块大小的表空间中!
注意您需要将适当的缓存大小设置为非零值。这也增加了数据库的 “惊喜因子”。我更喜欢基于函数的索引方法之一,而不是这个。
是的,确实会:
create table t (
c1 varchar2(2000 char),
c2 varchar2(4000 byte)
);
insert into t values ( 'x', rpad ( 'x', 4000, 'x' ) );
select lengthc ( c2 ) from t;
LENGTHC(C2)
4000 I'm considering VARCHAR2(4000 BYTE) with a check constraint LENGTHC(col) <= 2000.
Would you see a downside to this?
无法想到任何事情; 由于现有的应用程序已经仅限于2,000个字符,因此不应该出现功能问题。我主要关心的是 “惊喜因素”。也就是说,这是不寻常的事情,所以将来可能会赶上开发人员/dba。
Or is the best way simply to ignore the ORA-01450 errors, alter the columns after the import, and then create the indexes?
这是一个选择;)
您可以通过在索引定义中使用SUBSTR或STANDARD_HASH来解决该问题。优化器可以在不改变查询的情况下使用标准哈希函数进行相等:
create index i2
on t ( standard_hash ( c2 ) );
insert into t values ( 'c1', 'c2' );
set serveroutput off
select * from t
where c2 = 'c2';
select *
from dbms_xplan.display_cursor(format => 'BASIC LAST +PREDICATE');
----------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T |
|* 2 | INDEX RANGE SCAN | I2 |
----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("C2"='c2' AND INTERNAL_FUNCTION("T"."C1")))
2 - access("T"."SYS_NC00003$"=HEXTORAW('6B1F53303A732CCC8C6AAE6640399
827C15250E3')) 您可以在文档中阅读有关此内容的更多信息https://docs.oracle.com/en/database/oracle/oracle-database/20/sqlrf/CREATE-INDEX.html#GUID-1F89BBC0-825F-4215-AF71-7588E31D8BFE
Any other ideas or tips that might be beneficial?
问题是索引键的数据必须小于索引块大小减去一些开销。所以还有另一种解决方法:
将索引放在具有更大块大小的表空间中!
create index i on t ( c1 ); ORA-01450: maximum key length (6398) exceeded sho parameter db_16K_cache_size NAME TYPE VALUE ----------------- ----------- ----- db_16k_cache_size big integer 16M sho parameter max_string NAME TYPE VALUE --------------- ------ -------- max_string_size string EXTENDED create tablespace tblsp_16k datafile 'tblsp_32k' size 1M blocksize 16384; create index i on t ( c1 ) tablespace tblsp_16k; select tablespace_name from user_indexes where index_name = 'I'; TABLESPACE_NAME TBLSP_16K
注意您需要将适当的缓存大小设置为非零值。这也增加了数据库的 “惊喜因子”。我更喜欢基于函数的索引方法之一,而不是这个。
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




