繁体   English   中英

Postgres SQL中的字符串字段长度

[英]String field length in Postgres SQL

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

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

url_field = Column(String(256))

这是否占用每行的空间(存储),即使实际的字符串更短?

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

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

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

合格的varchar(n)与非限定的varchar基本相同,并且length(colname) < ncheck约束。

尽管其他一些评论/答案都在说, char(n)varcharvarchar(n)text都是TOASTable类型。 它们都可以存储在线外和/或压缩。 要控制存储,请使用ALTER TABLE ... ALTER COLUMN ... SET STORAGE

如果您不知道所需的最大长度,只需使用text或unqualified varchar 没有空间罚款。

有关更多详细信息,请参阅有关字符数据类型的文档 ,以及有关如何存储它们的一些内容,请参阅特别是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很有用,其中大小限制可能会影响存储。

postgreSQL,sqllite和mysql都应用sql标准来存储varchar和chars。 这是基本的:

SQL定义了两种主要字符类型:字符变化(n)和字符(n),其中n是正整数。 这两种类型都可以存储长度最多为n个字符的字符串。 尝试将较长的字符串存储到这些类型的列中将导致错误,除非多余的字符都是空格,在这种情况下,字符串将被截断为最大长度。 (这个有点奇怪的异常是SQL标准所要求的。)如果要存储的字符串比声明的长度短,则字符类型的值将被空格填充; 类型字符变量的值将只存储较短的字符串。

如果显式地将值转换为字符变量(n)或字符(n),则超长值将被截断为n个字符而不会引发错误。 (这也是SQL标准所要求的。)

符号varchar(n)和char(n)分别是字符变化(n)和字符(n)的别名。 没有长度说明符的字符等同于字符(1)。 如果在没有长度说明符的情况下使用字符变化,则该类型接受任何大小的字符串。 后者是PostgreSQL扩展。

参考:

通常,数据库存储引擎可以做很多你不期望的事情。 但基本上,有两种文本字段,它们提示内部会发生什么。

char和varchar。 Char将为您提供固定的字段列,并且根据sql会话中的选项,您可能会收到空格填充的字符串。 Varchar用于最大长度的文本字段。

Varchar字段可以存储为块外部的指针,以便块在查询上保持可预测的大小 - 但这是一个实现细节,可能因db而异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM