我在SQL数据库中有一个字符串,代表一个网址。有些网址很短,有些很长。我真的不知道waht是我可能遇到的最长的URL,所以为了安全起见,我会采用一个很大的值,例如256或512.
当我定义最大字符串长度时(例如使用SQLAlchemy):
url_field = Column(String(256))
这会占用每行的空间(存储空间),即使实际字符串较短吗?
我假设这与实现细节有关。我正在使用postgreSQL,但我也对sqlite,mysql感兴趣。
答案 0 :(得分:8)
在PostgreSQL中character(n)
基本上只是varchar
,在输入/输出上有空格填充。它很笨拙,应该避免。它使用与varchar
或text
字段相同的存储空间,该字段已填充到最大长度(参见下文)。 char(n)
是一个历史性的疣,应该避免 - 至少在PostgreSQL中它没有任何优势,并且有一些像left(...)
这样的奇怪怪癖。
varchar(n)
,varchar
和text
都使用相同的存储空间 - 您提供的字符串长度没有填充。它只使用字符实际需要的存储空间,而不管长度限制。此外,如果字符串为null,PostgreSQL根本不存储它的值(甚至不是长度标题),它只是在记录的空位图中设置空位。
符合条件的varchar(n)
与varchar
上check
约束的非限定length(colname) < n
基本相同。
尽管其他一些评论/答案都在说,char(n)
,varchar
,varchar(n)
和text
都是TOASTable类型。它们都可以存储在线外和/或压缩。要控制存储空间使用ALTER TABLE ... ALTER COLUMN ... SET STORAGE
。
如果您不知道所需的最大长度,请使用text
或不合格的varchar
。没有空间罚款。
有关详细信息,请参阅the documentation on character data types,以及有关如何存储内容的一些内容,请参阅database physical storage,特别是TOAST。
演示:
CREATE TABLE somechars(c10 char(10), vc10 varchar(10), vc varchar, t text);
insert into somechars(c10) values (' abcdef ');
insert into somechars(vc10) values (' abcdef ');
insert into somechars(vc) values (' abcdef ');
insert into somechars(t) values (' abcdef ');
为每个col输出此查询:
SELECT 'c10', pg_column_size(c10), octet_length(c10), length(c10)
from somechars where c10 is not null;
是:
?column? | pg_column_size | octet_length | length
c10 | 11 | 10 | 8
vc10 | 10 | 9 | 9
vc | 10 | 9 | 9
t | 10 | 9 | 9
pg_column_size
是字段中数据的磁盘大小。 octet_length
是没有标题的未压缩大小。 length
是“逻辑”字符串长度。
如您所见,char
字段已填充。虽然输入是9个字符,而不是8,但它也会给length
带来非常令人惊讶的结果。这是因为Pg无法区分你自己的领先空间和领先它添加为填充的空格。
因此,请勿使用char(n)
。
顺便说一句,如果我正在设计一个数据库,我从不使用varchar(n)
或char(n)
。我只是使用text
类型并添加适当的check
约束,如果有值的应用程序要求。我认为varchar(n)
在标准中有点像疣,但我认为这对于具有磁盘布局的DB很有用,其中大小限制可能会影响存储。
答案 1 :(得分:1)
postgreSQL,sqllite和mysql都应用sql标准来存储varchar和chars。这基本上是这样的:
SQL定义了两种主要的字符类型:字符变化(n)和 character(n),其中n是正整数。这两种类型都可以 存储最多n个字符的字符串。试图存储一个 较长的字符串到这些类型的列将导致错误, 除非多余的字符都是空格,在这种情况下是字符串 将被截断为最大长度。 (这有点奇怪 SQL标准需要异常。)如果要存储的字符串 比声明的长度短,类型字符的值将是 空格填充;类型字符变化的值将简单地存储 较短的字符串。
如果显式地将值转换为字符变化(n)或 如果是字符(n),那么超长值将被截断为n 字符没有引发错误。 (这也是SQL所必需的 标准)。
符号varchar(n)和char(n)是字符的别名 分别变化(n)和字符(n)。没有长度的字符 说明符等同于字符(1)。如果使用字符变化 如果没有长度说明符,则该类型接受任何大小的字符串。该 后者是PostgreSQL扩展。
参考:
答案 2 :(得分:0)
通常,数据库存储引擎可以做很多你不期望的事情。但基本上,有两种文本字段,它们提示内部会发生什么。
char和varchar。 Char将为您提供固定的字段列,并且根据sql会话中的选项,您可能会收到空格填充的字符串。 Varchar用于最大长度的文本字段。
可以将varchar字段存储为块外部的指针,以便块在查询上保持可预测的大小 - 但这是一个实现细节,可能因db而异。