Postgresql中的字符串字段长度

时间:2014-06-02 06:25:12

标签: sql postgresql sqlalchemy

我在SQL数据库中有一个字符串,代表一个网址。有些网址很短,有些很长。我真的不知道waht是我可能遇到的最长的URL,所以为了安全起见,我会采用一个很大的值,例如256或512.

当我定义最大字符串长度时(例如使用SQLAlchemy):

url_field = Column(String(256))

这会占用每行的空间(存储空间),即使实际字符串较短吗?

我假设这与实现细节有关。我正在使用postgreSQL,但我也对sqlite,mysql感兴趣。

3 个答案:

答案 0 :(得分:8)

在PostgreSQL中character(n)基本上只是varchar,在输入/输出上有空格填充。它很笨拙,应该避免。它使用与varchartext字段相同的存储空间,该字段已填充到最大长度(参见下文)。 char(n)是一个历史性的疣,应该避免 - 至少在PostgreSQL中它没有任何优势,并且有一些像left(...)这样的奇怪怪癖。

varchar(n)varchartext都使用相同的存储空间 - 您提供的字符串长度没有填充。它只使用字符实际需要的存储空间,而不管长度限制。此外,如果字符串为null,PostgreSQL根本不存储它的值(甚至不是长度标题),它只是在记录的空位图中设置空位。

符合条件的varchar(n)varcharcheck约束的非限定length(colname) < n基本相同。

尽管其他一些评论/答案都在说,char(n)varcharvarchar(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而异。