问题描述
嗨,甲骨文大师团队
我在具有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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
【专家有话说第五期】在不同年龄段,DBA应该怎样规划自己的职业发展?
墨天轮编辑部
1320次阅读
2025-03-13 11:40:53
Oracle RAC ASM 磁盘组满了,无法扩容怎么在线处理?
Lucifer三思而后行
790次阅读
2025-03-17 11:33:53
Oracle+Deepseek+Dify 实现数据库数据实时分析
bicewow
721次阅读
2025-03-06 09:41:49
【ORACLE】ORACLE19C在19.13版本前的一个严重BUG-24761824
DarkAthena
577次阅读
2025-03-04 14:33:31
Oracle避坑指南|同名表导出难题:如何精准排除指定用户下的表?
szrsu
541次阅读
2025-03-05 00:42:34
2月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
462次阅读
2025-03-13 14:38:19
Ogg23ai高手必看-MySQL Innodb Cluster跟oracle的亲密接触
曹海峰
461次阅读
2025-03-04 21:56:13
【ORACLE】char类型和sql优化器发生的“错误”反应
DarkAthena
411次阅读
2025-03-04 23:05:01
Oracle 如何修改 db_unique_name?强迫症福音!
Lucifer三思而后行
351次阅读
2025-03-12 21:27:56
Oracle DataGuard高可用性解决方案详解
孙莹
314次阅读
2025-03-26 23:27:33