在没有业务约束的情况下,我应该为 Oracle 字符类型设置什么限制?
What limit should I set for Oracle character types, when there is no business constraint?
我习惯于为 PostgreSQL 设计,其字符类型没有性能差异,并且社区的建议是明确限制仅存在于执行业务规则。
https://www.postgresql.org/docs/current/datatype-character.html
现在我在 Oracle (19c) 工作。我对字符类型的选择似乎是具有强制限制的 VARCHAR2 或 CLOB。
社区的建议似乎是尽可能避免使用 CLOB。我不清楚这是出于性能原因、传统原因,还是因为 CLOB 在没有一些操作的情况下不会显示在查询编辑器中。
如果业务或领域没有规定文本字段的最大长度,那么在选择限制时我应该考虑哪些技术、性能或用户体验因素?
"这是否是出于性能原因" - 那。 CLOB 在 Oracle 中非常慢(特别是如果你经常改变它们)
如果没有业务规则且 4000 字节 (!) 暂时似乎足够,请使用 varchar2(4000)
。
不要试图使用允许 varchar2(32767)
的扩展 varchars - 它们在后台存储为 CLOB 并遭受相同的性能问题。
TL;DR: 避免 CLOB,使用长度合理的 VARCHAR2。
我完全同意@a_horse_with_no_name 关于 CLOB 和 varchar2(32767)
。
不过,我不建议将最大尺寸设置为VARCHAR2(4000)
,而是使用一个合理的上限,这实际上很难估计。如果字段太短,用户和其他开发人员会讨厌你。如果字段太长,数据库会做一些奇怪的事情。
因为VARCHAR2
只存储实际使用的字符,所以在存储方面你不会发现任何差异,它在插入、更新或删除时的性能很可能是相同的。
但是,有时 Oracle 假设实际使用了最大长度:
CREATE TABLE t (
a VARCHAR2( 1 CHAR),
b VARCHAR2( 1 CHAR),
c VARCHAR2(4000 CHAR),
d VARCHAR2(4000 CHAR)
);
CREATE INDEX i1 ON t(a,b);
Index I1 created.
CREATE INDEX i1000 ON t(c, d);
ORA-01450: maximum key length (6398) exceeded
此外,当数据库服务器(或客户端应用程序)按最大长度分配内存时,有时会影响性能,例如:
INSERT INTO t SELECT 'a','a','a','a' FROM all_objects;
INSERT INTO t SELECT 'b','b','b','b' FROM all_objects;
INSERT INTO t SELECT 'c','c','c','c' FROM all_objects;
INSERT INTO t SELECT 'd','d','d','d' FROM all_objects;
EXECUTE dbms_stats.gather_table_stats(null, 't');
SET AUTOTRACE TRACEONLY STAT
现在在内存中按 VARCHAR2(1)
列排序(速度很快):
SELECT a,b FROM t ORDER BY a,b;
Statistics
----------------------------------------------------------
1 sorts (memory)
0 sorts (disk)
268520 rows processed
虽然按 VARCHAR2(4000)
列排序不适合内存,因此必须在磁盘上排序,这很慢:
SELECT c,d FROM t ORDER BY c,d;
Statistics
----------------------------------------------------------
0 sorts (memory)
1 sorts (disk)
268520 rows processed
我不得不承认我将可用内存设置得非常小只是为了证明这一点,但我想你明白了。
我习惯于为 PostgreSQL 设计,其字符类型没有性能差异,并且社区的建议是明确限制仅存在于执行业务规则。
https://www.postgresql.org/docs/current/datatype-character.html
现在我在 Oracle (19c) 工作。我对字符类型的选择似乎是具有强制限制的 VARCHAR2 或 CLOB。
社区的建议似乎是尽可能避免使用 CLOB。我不清楚这是出于性能原因、传统原因,还是因为 CLOB 在没有一些操作的情况下不会显示在查询编辑器中。
如果业务或领域没有规定文本字段的最大长度,那么在选择限制时我应该考虑哪些技术、性能或用户体验因素?
"这是否是出于性能原因" - 那。 CLOB 在 Oracle 中非常慢(特别是如果你经常改变它们)
如果没有业务规则且 4000 字节 (!) 暂时似乎足够,请使用 varchar2(4000)
。
不要试图使用允许 varchar2(32767)
的扩展 varchars - 它们在后台存储为 CLOB 并遭受相同的性能问题。
TL;DR: 避免 CLOB,使用长度合理的 VARCHAR2。
我完全同意@a_horse_with_no_name 关于 CLOB 和 varchar2(32767)
。
不过,我不建议将最大尺寸设置为VARCHAR2(4000)
,而是使用一个合理的上限,这实际上很难估计。如果字段太短,用户和其他开发人员会讨厌你。如果字段太长,数据库会做一些奇怪的事情。
因为VARCHAR2
只存储实际使用的字符,所以在存储方面你不会发现任何差异,它在插入、更新或删除时的性能很可能是相同的。
但是,有时 Oracle 假设实际使用了最大长度:
CREATE TABLE t (
a VARCHAR2( 1 CHAR),
b VARCHAR2( 1 CHAR),
c VARCHAR2(4000 CHAR),
d VARCHAR2(4000 CHAR)
);
CREATE INDEX i1 ON t(a,b);
Index I1 created.
CREATE INDEX i1000 ON t(c, d);
ORA-01450: maximum key length (6398) exceeded
此外,当数据库服务器(或客户端应用程序)按最大长度分配内存时,有时会影响性能,例如:
INSERT INTO t SELECT 'a','a','a','a' FROM all_objects;
INSERT INTO t SELECT 'b','b','b','b' FROM all_objects;
INSERT INTO t SELECT 'c','c','c','c' FROM all_objects;
INSERT INTO t SELECT 'd','d','d','d' FROM all_objects;
EXECUTE dbms_stats.gather_table_stats(null, 't');
SET AUTOTRACE TRACEONLY STAT
现在在内存中按 VARCHAR2(1)
列排序(速度很快):
SELECT a,b FROM t ORDER BY a,b;
Statistics
----------------------------------------------------------
1 sorts (memory)
0 sorts (disk)
268520 rows processed
虽然按 VARCHAR2(4000)
列排序不适合内存,因此必须在磁盘上排序,这很慢:
SELECT c,d FROM t ORDER BY c,d;
Statistics
----------------------------------------------------------
0 sorts (memory)
1 sorts (disk)
268520 rows processed
我不得不承认我将可用内存设置得非常小只是为了证明这一点,但我想你明白了。