经朋友介绍,我读完 Tim Hall 于 2022 年 9 月 27 日他的博客上发表的博文。10 月 11 日星期二是 “Oracle 社区活动日”,但在2021年,它被重命名为“乔尔·卡尔曼日”。乔尔对社区很感兴趣,这似乎是对他的恰当致敬。所以许多人和朋友都在这一日写帖子并带上 #JoelKallmanDay.

这无疑对社区的每个人都有很大的情感意义。所以,推荐我写的朋友也呼唤我也写点东西来支持这个活动。但是写什么呢?由于这是我第一次写,所以就写一个 Oracle 新特性吧。于是乎就用我蹩脚的英语加有道词典花了两个晚上写了人生中第一篇英文博客《Increased Size Limit for VARCHAR2, NVARCHAR2, and RAW Data Types#JoelKallmanDay》。并且第二日 Tim Hall 大师将来自全球的六、七十位社区伙伴的博客汇总到一起,如下,我的文章刚好被排在第六位。

下面我打算在原有英文的基础上修改修改,翻译回中文,使读起来更顺畅,排版更美观。

On the Oracle New Features Website, there is a new feature about extending data types“The maximum size of the VARCHAR2, NVARCHAR2, and RAW data types has been increased from 4,000 to 32,767 bytes“.

在 Oracle 新特性网站上,有一个关于扩展数据类型的新特性 “VARCHAR2、NVARCHAR2 和 RAW 数据类型的最大大小已从 4000 增加到 32,767 字节”。

我认为它很有趣,很喜欢,也很实用,所以我想介绍它。

以 Varchar2 数据类型为例:

The VARCHAR2 data type specifies a variable-length character string in the database character set. You specify the database character set when you create your database.

VARCHAR2 数据类型在数据库字符集中指定一个可变长度的字符串。在创建数据库时指定数据库字符集。

When you create a table with a VARCHAR2 column, you must specify the column length as size optionally followed by a length qualifier. The qualifier BYTE denotes byte length semantics while the qualifier CHAR denotes character length semantics. In the byte length semantics, size is the maximum number of bytes that can be stored in the column. In the character length semantics, size is the maximum number of code points in the database character set that can be stored in the column. A code point may have from 1 to 4 bytes depending on the database character set and the particular character encoded by the code point. Oracle recommends that you specify one of the length qualifiers to explicitly document the desired length semantics of the column. If you do not specify a qualifier, the value of the NLS_LENGTH_SEMANTICS parameter of the session creating the column defines the length semantics, unless the table belongs to the schema SYS, in which case the default semantics is BYTE.

当创建带有 VARCHAR2 列的表时,必须将列长度指定为可选的大小,后面跟着一个长度限定符。限定符 BYTE 表示字节长度语义,而限定符 CHAR 表示字符长度语义。在字节长度语义中,size 是列中可以存储的最大字节数。在字符长度语义中,size 是数据库字符集中可以存储在列中的代码点的最大数量。一个代码点可能有 1 到 4 个字节,这取决于数据库字符集和代码点编码的特定字符。Oracle 建议您指定一个长度限定符来显式记录列所需的长度语义。如果不指定限定符,则创建列的会话的 NLS_LENGTH_SEMANTICS 参数的值定义长度语义,除非表属于模式 SYS,在这种情况下默认语义为 BYTE。

Oracle stores a character value in a VARCHAR2 column exactly as you specify it, without any blank-padding, provided the value does not exceed the length of the column. If you try to insert a value that exceeds the specified length, then Oracle returns an error ORA-12899.

Oracle 在 VARCHAR2 列中存储的字符值与您指定的完全一致,没有任何空白填充,只要该值不超过列的长度。如果试图插入一个超过指定长度的值,Oracle 将返回一个 ORA-12899:value too large for column “SYS”.“T5”.“E” (actual: 4000, maximum: 3999) 错误。

However, in the Oracle 19c official documentation description,The minimum value of size is 1. The maximum value is:

  • 32767 bytes if MAX_STRING_SIZE = EXTENDED
  • 4000 bytes if MAX_STRING_SIZE = STANDARD

但是在 Oracle 19c 官方文档中,size 的最小值是 1。最大值为 4000 或者 32767 是需要根据参数 MAX_STRING_SIZE 的值确定,当值为 EXTENDED 时,size 大小才可以为 32767。

While size may be expressed in bytes or characters (code points) the independent absolute maximum length of any character value that can be stored into a VARCHAR2 column is 32767 or 4000 bytes, depending on MAX_STRING_SIZE. For example, even if you define the column length to be 32767 characters, Oracle returns an error if you try to insert a 32767-character value in which one or more code points are wider than 1 byte. The value of size in characters is a length constraint, not guaranteed capacity. If you want a VARCHAR2 column to be always able to store size characters in any database character set, use a value of size that is less than or equal to 8191, if MAX_STRING_SIZE = EXTENDED, or 1000, if MAX_STRING_SIZE = STANDARD.

虽然大小可以用字节或字符(码位)表示,但可以存储到 VARCHAR2 列中的任何字符值的独立绝对最大长度是 32767 或 4000 字节,这取决于 MAX_STRING_SIZE。例如,即使您将列长度定义为 32767 个字符,如果您试图插入一个 32767 个字符的值,其中一个或多个编码点的宽度大于 1 字节,Oracle 也会返回一个错误。字符大小的值是长度限制,而不是容量保证。如果希望 VARCHAR2 列始终能够在任何数据库字符集中存储大小字符,如果 MAX_STRING_SIZE = EXTENDED,则使用小于或等于 8191 的size 值;如果 MAX_STRING_SIZE = STANDARD,则使用小于或等于 1000 的 size 值。

However, I found that the MAX_STRING_SIZE parameter does not need to be set to EXTENDED to create the varchar2 extension data type and insert the data successfully.The following is my test in each version of the database. Isn’t it interesting that there is a discrepancy with the official Oracle documentation?

但是,我发现不需要将 MAX_STRING_SIZE 参数设置为 EXTENDED 来创建 varchar2 扩展数据类型,并成功插入数据。以下是我在每个版本的数据库中的测试。与 Oracle官方文档描述的有点差异,这是不是很有趣呢?

DB Version 19.15

DB Version 19.15

(db 19.15)

DB Version 19.4

sqlplus / as sysdba
set timing on time on SQL*Plus: Release 19.0.0.0.0 - Production on Mon Oct 10 13:43:15 2022
Version 19.4.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.4.0.0.0 show parameter max_string_size NAME TYPE VALUE max_string_size string STANDARD 14:02:42 SYS@JiekeXu> create table T1(C clob, E varchar2(32737)); Table created.
14:03:09 SYS@JiekeXu> insert into t1 select lpad(rownum,32767,'X'),lpad(rownum,32767,'X') from dual connect by level <=10; 10 rows created.
14:03:14 SYS@JiekeXu> commit; Commit complete. 14:03:19 SYS@JiekeXu> set autot trace stat
14:04:04 SYS@JiekeXu> select C from t1;

DB Version 19.3

(db 19.3)

DB Version 12.2

(db 12.2)

Because I don’t have the database versions of Oracle 12.1.0.1 and 12.0.1.2 for the moment, I can’t test it. I wonder whether these two versions need to set parameters and restart the database.Interested friends with the environment can test whether the following results are correct.

因为我当前没有 Oracle 12.1.0.1 和 12.0.1.2 的数据库版本,所以我不能测试它。我想知道这两个版本是否需要设置参数并重新启动数据库。对 12.1 环境感兴趣的朋友可以测试下是否正确,是否需要修改参数并跑 utl32k.sql 脚本。

So what’s the problem? You know what? Give me a homework assignment.

那么问题是什么呢?你知道吗?继续往下看,后面会揭秘。

So what are the benefits of Extended Data types?
那么扩展数据类型的好处是什么呢?

Increasing the allotted size for these data types allows users to store more information in character data types before switching to large objects (LOBs). This is especially useful for brief textual data types and the capabilities to build indexes on these types of columns And Extended VARCHAR2 reduces the number of network round-trips.

增加这些数据类型的分配大小允许用户在切换到大对象(lob)之前在字符数据类型中存储更多的信息。这对于简短的文本数据类型以及在这些类型的列上构建索引的功能尤其有用。Extended VARCHAR2 减少了网络往返的数量。

Update on Day 2

Today, my friend sent me a screenshot of version 12.1.0.2.The result is a direct error in the SQL construct sentence.

今天,我的朋友给我发了一张 12.1.0.2 版本的运行截图。结果是 SQL语句在建表时就抛出了一个数据类型太长的错误。

(db 12.1.0.2)

In the test process of version 12.2, it is found that no matter how large the size is, it can be successfully created.So why is this happening? Let’s move on.

在 12.2 版本的测试过程中发现,无论 size 大小有多大,表都可以成功创建,而且数据也会插入成功。那么,为什么会出现这种情况呢?让我们继续。

Now for the reveal 开始揭秘

在我的一台单机的 19.12 的环境下,创建表进行测试。

create table T1(id int, E varchar2(32767));
CREATE SEQUENCE SEQ_T1 MINVALUE 1 MAXVALUE 99999999999999 INCREMENT BY 1 START WITH 1 CACHE 50 ORDER NOCYCLE;
insert into t1 values(SEQ_T1.nextval,lpad('x',32767,'x'));
insert into t1 values(SEQ_T1.nextval,lpad('x',32768,'x'));
commit;
select length(E) from t1;

And you can see that whether I use 32767 or 32768 I’m going to end up with a length of 4000.So the official document says there is no error, we have to modify the parameter MAX_STRING_SIZE = EXTENDED .

你可以看到,无论我用 32767 还是 32768,最终长度都是 4000。所以官方文档说没有错误,我们必须修改参数 MAX_STRING_SIZE = EXTENDED。

(database must in UPGRADE mode)

数据库需要 startup UPGRADE 以升级模式启动,然后才能修改参数,并且需要跑脚本 utl32k.sql,然后关闭数据库再正常重启数据库。

Therefore, it can be seen from the above that under normal circumstances, the maximum value of varchar2 can only be 4000, and the excess part will be truncated. After the database is started in upgrade mode, utl32k.sql is run, and parameters are modified, vatchar2 can store up to 32767 bytes, and the excess bytes are truncated.

因此,由上表可以看出,在正常情况下,varchar2 的最大值只能为 4000,多余的部分会被截断。数据库以升级模式启动后,修改参数,跑 utl32k.sql 脚本再正常重启数据库。vatchar2 最多可以存储 32767 个字节,多余的字节被截断。顺便说一句,NVARCHAR2 和 RAW 在这场景下最多也可以存储 32767 个字节。

值得注意的是如果您的数据库是 RAC,需要关闭 node2 并修改集群参数 CLUSTER_DATABASE=FALSE。如果你的数据库还有 ADG 备库,请立即修改 MAX_STRING_SIZE 并重启,否则备库不修改此参数会导致 MRP0 进程异常宕掉,造成主备数据不同步的情况。

node2: shu immediate

node1:
alter system set CLUSTER_DATABASE=FALSE scope=spfile;
alter system set MAX_STRING_SIZE = EXTENDED scope=spfile;
shu immediate
startup upgrade
@?/rdbms/admin/utl32k.sql alter system set CLUSTER_DATABASE=TRUE scope=spfile;
shu immediate
startup
show parameter max_string_size
create table T1(E varchar2(32767));
insert into t1 values(lpad(‘x’,32767,’x’));
commit;
select length(E) from t1; node2: startup ----ADG instance
alter system set CLUSTER_DATABASE=TRUE scope=spfile;
shu immediate
startup
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;

Summary 总结

扩展数据类型
从 Oracle Database 12c 开始,您可以为 VARCHAR2、NVARCHAR2 和 RAW 数据类型指定最大大小为 32767 字节。可以通过设置初始化参数 MAX_STRING_SIZE 来控制您的数据库是否支持这个新的最大大小,如下所示:

  • 如果 MAX_STRING_SIZE = STANDARD,则适用于 Oracle Database 12c 之前的版本的大小限制:VARCHAR2 和 NVARCHAR2 数据类型为 4000 字节,RAW 数据类型为2000 字节。这是默认设置。

  • 如果 MAX_STRING_SIZE = EXTENDED,则 VARCHAR2、NVARCHAR2 和 RAW 数据类型的大小限制为 32767 字节。

声明大小大于 4000 字节的 VARCHAR2 或 NVARCHAR2 数据类型,或声明大小大于 2000 字节的 RAW 数据类型,都是扩展数据类型。扩展的数据类型列是在线存储的,利用 Oracle 的 LOB 技术。LOB 存储始终与表对齐。在使用自动段空间管理(ASSM)管理的表空间中,扩展的数据类型列存储为 SecureFiles lob。否则,它们被存储为BasicFiles lob。lob 作为存储机制的使用只是内部的。因此,您不能使用 DBMS_LOB 包操作这些 lob。Oracle 强烈反对使用 BasicFiles lob 作为存储机制。BasicFiles lob 不仅对扩展数据类型列的功能施加了限制,而且计划在未来的版本中弃用 BasicFiles 数据类型。

注意,尽管必须设置 MAX_STRING_SIZE = EXTENDED 才能将 RAW 数据类型的大小设置为大于 2000 字节,但只有当 RAW 数据类型的大小大于 4000 字节时,它才被存储为 out-of-line LOB。例如,为了声明 RAW(3000)数据类型,必须设置MAX_STRING_SIZE = EXTENDED。但是,列是内联存储的。

注意事项

您可以像使用标准数据类型一样使用扩展数据类型,需要注意以下事项:

1、如果列是扩展数据类型列,则在尝试创建索引时可能会收到“超出最大键长度”错误。索引的最大键长度取决于数据库块大小和存储在块中的一些附加索引元数据。例如,对于使用 Oracle 标准 8K 块大小的数据库,最大密钥长度约为 6400 字节。

要解决这种情况,您必须使用以下方法之一缩短要索引的值的长度:

  • 创建基于函数的索引以缩短存储在扩展数据类型列中的值,作为用于索引定义的表达式的一部分。
  • 创建虚拟列以缩短存储在扩展数据类型列中的值,作为用于虚拟列定义的表达式的一部分,并在虚拟列上构建普通索引。使用虚拟列还使您能够利用常规列的功能,例如收集统计信息以及使用约束和触发器。

对于这两种方法,您都可以使用 SUBSTR 或者 STANDARD_HASH 函数来缩短扩展数据类型列的值以构建索引。这些方法具有以下优点和缺点:

  • 使用该 SUBSTR 函数返回一个子字符串或前缀,column 它是索引键可接受的长度。这种类型的索引可用于原始列上的相等、IN-list 和范围谓词,而无需将SUBSTR列指定为谓词的一部分。
  • 使用该 STANDARD_HASH 函数可能会创建一个比基于子字符串的索引更紧凑的索引,并且可能会减少不必要的索引访问。这种类型的索引可用于原始列上的相等和 IN-list 谓词,而无需将 STANDARD_HASH 列指定为谓词的一部分。

以下示例显示如何在扩展数据类型列上创建基于函数的索引:

CREATE INDEX index ON table (SUBSTR(column, 1, n));

---- 对于 n,指定一个足够大的前缀长度以区分列中的值。

以下示例显示如何为扩展数据类型列创建虚拟列,然后在虚拟列上创建索引:

ALTER TABLE table ADD (new_hash_column AS (STANDARD_HASH(column)));
CREATE INDEX index ON table (new_hash_column);

2、如果列表分区的分区键列是扩展数据类型列,则希望为分区指定的值列表可能超过分区边界的4K字节限制。有关如何解决此问题的信息, 请参阅 create table 的 list_partitions子句。

3、初始化参数的值 MAX_STRING_SIZE 会影响以下内容:

  • 文本文字的最大长度。有关详细信息,请参阅文本字面量。
  • 连接两个字符串的大小限制。有关详细信息,请参阅串联运算符。
  • NLSSORT 函数返回的排序规则键的长度。请参阅 NLSSORT。
  • 对象的某些属性的大小 XMLFormat。有关详细信息,请参阅 XML 格式模型。
  • 以下 XML 函数中某些表达式的大小:XMLCOLATTVAL、XMLELEMENT、XMLFOREST、XMLPI 和 XMLTABLE。

全文完,希望可以帮到正在阅读的你,如果觉得有帮助,可以分享给你身边的朋友,同事,你关心谁就分享给谁,一起学习共同进步~~~

️ 欢迎关注我的公众号【JiekeXu DBA之路】,一起学习新知识!

[转帖]Oracle 19c 新特性|增加 VARCHAR2 数据类型的大小限制的更多相关文章

  1. Oracle 12C 新特性之扩展数据类型(extended data type)

    Oracle 12C 新特性-扩展数据类型,在12c中,与早期版本相比,诸如VARCHAR2, NAVARCHAR2以及 RAW这些数据类型的大小会从4K以及2K字节扩展至32K字节.只要可能,扩展字 ...

  2. Oracle 12c新特性

    转载自:Oracle 12c新特性(For DBA) 一: Multitenant Architecture (12.1.0.1)      多租户架构是Oracle 12c(12.1)的新增重磅特性 ...

  3. Oracle 11g 新特性 --SQL Plan Management 说明

    Oracle 11g 新特性 --SQL Plan Management 说明 参见大神博主文章: http://blog.csdn.net/tianlesoftware/article/detail ...

  4. Oracle 11g 新特性 – HM(Hang Manager)简介

    在这篇文章中我们会对oracle 11g 新特性—hang 管理器(Hang Manager) 进行介绍.我们需要说明,HM 只在RAC 数据库中存在. 在我们诊断数据库问题的时候,经常会遇到一些数据 ...

  5. Oracle 11g新特性

    文章转自网络 Oracle 11g于2007年7月11日美国东部时间11时(北京时间11日22时)正式发布,11g是甲骨文公司30年来发布的最重要的数据库版本,根据用户的需求实现了信息生命周期管理(I ...

  6. Oracle 11g 新特性(一)-- 虚拟列

    数据库版本: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Oracle11g 增加了虚拟列的新特性, 具体说明如 ...

  7. Oracle 12c 新特性之 数据库内归档(In-Database Archiving)

    Oracle Database 12c中引入了 In-Database Archiving的新特性, 该特性允许用户通过对表上的数据行标记为inactive不活跃的,以归档数据. 这些inactive ...

  8. Oracle 11g新特性 -- 延迟段

    11gR2之前的版本中,当创建一张表时,会自动分配段空间,这样做有几个弊端: 1. 初始创建表时就需要分配空间,自然会占用一些时间,如果初始化多张表,这种影响就被放大. 2. 如果很多表开始的一段时间 ...

  9. Oracle 18c新特性一览

    1. 一般新特性 1.1. Shadow Lost Write Protection Shadow lost write protection检测到一个丢失的写,它会导致一个主要的数据损坏.可以在不需 ...

  10. ORACLE 12C新特性——CDB与PDB

    Oracle 12C引入了CDB与PDB的新特性,在ORACLE 12C数据库引入的多租用户环境(Multitenant Environment)中,允许一个数据库容器(CDB)承载多个可插拔数据库( ...

随机推荐

  1. BFS(一)单词接龙

    对应 LeetCode 127 单词接龙 问题定义 给定一个字典序列 wordList,一个初始的单词 beginWord 和一个目标单词 endWord,现在要求每次变换满足以下条件将 beginW ...

  2. 不是银趴~是@Import!

    首先我们要明确:@Import 注解是 Spring 提供的. 然后我们看一下该注解的官方注释: Indicates one or more component classes to import - ...

  3. c#中用System.Diagnostics.Process.Start(Path.GetFullPath(“vlc.exe.lnk“), url);用vlc的快捷方式打开http的url不起作用?

    vlc.exe.lnk双击这个文件,能正常打开vlc,但是用System.Diagnostics.Process.Start(Path.GetFullPath("vlc.exe.lnk&qu ...

  4. 海量监控数据处理如何做,看华为云SRE案例分享

    摘要:openGemini的设计和优化都是根据时序数据特点而来,在面对海量运维监控数据处理需求时,openGemini显然更加有针对性. IT运维诞生于最早的信息化时代.在信息化时代,企业的信息化系统 ...

  5. Python 初学者必看:Python 异常处理集合

    摘要:作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息,本文专门介绍 python 异常处理. 异常 广义上的错误分为错误和异常 错误指的是可以人为避免 异常是指在语 ...

  6. 一文讲清楚FusionInsight MRS CDL如何使用

    摘要:CDL是一种简单.高效的数据实时集成服务,能够从各种OLTP数据库中抓取Data Change事件,然后推送至Kafka中,最后由Sink Connector消费Topic中的数据并导入到大数据 ...

  7. 让数据大白于天下:GCC插件实现代码分析和安全审计

    摘要: 如何利用GCC的插件功能,辅助安全分析人员实现对程序的安全审计.漏洞检测.安全加固等自动化处理能力,提升分析效率和精准度. 本文分享自华为云社区<利用GCC插件实现代码分析和安全审计&g ...

  8. 2023 年如何将您的应用提交到 App Store

    您夜以继日地工作来创建您的梦想应用程序.最后,是时候向全世界宣布您的应用程序了.但不知道如何将您的应用提交到 App Store? 为您的商店获取现成的移动应用程序 将应用程序提交到 App Stor ...

  9. 火山引擎ByteHouse联合Apache Airflow,让数据管理更加高效

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   近日,火山引擎ByteHouse 正式宣布与 Apache Airflow 兼容,两者结合不仅可以高效地存储和 ...

  10. PPT 动画-滚动数字

    插入一个文本框,输入 0~9 调整边框大小,使其竖着排列 页面切换,选择平滑