在没有业务约束的情况下,我应该为Oracle字符类型设置什么限制?

问题描述 投票:0回答:1

我习惯于为PostgreSQL设计,其字符类型没有性能差异,社区的建议是,明确的限制只存在于执行业务规则。

https:/www.postgresql.orgdocscurrentdatatype-character.html

现在我在Oracle(19c)中工作。我对字符类型的选择似乎是带有强制限制的VARCHAR2,或者是CLOB。

社区的建议似乎是尽可能避免使用CLOB。我不清楚这是出于性能的原因、传统的原因,还是因为CLOB在查询编辑器中不经过一些操作就无法显示。

如果从业务上,或者领域上没有规则建议文本字段的最大长度,那么在选择限制时,我应该考虑哪些技术、性能或者用户体验因素?

oracle data-modeling oracle19c
1个回答
3
投票

"是否出于性能原因"--那。在Oracle中,CLOB的速度极慢(特别是当你经常改变它们的时候)。

如果没有业务规则,而且4000字节(!)似乎暂时够用了,就用 varchar2(4000).

不要被诱惑使用扩展的varchars,以允许 varchar2(32767) - 它们在后台被存储为CLOB,并遭受同样的性能问题。


1
投票

TL;DR: 避免使用CLOBs,使用合理长度的VARCHAR2。

我完全同意@a_horse_withno_name关于CLOBs和 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

我必须承认,我把可用的内存设置得很小,只是为了证明这一点,但我想你已经明白了。

© www.soinside.com 2019 - 2024. All rights reserved.