era*_*ran 2 sql postgresql sqlalchemy
我在SQL数据库中提交了一个字符串,表示一个URL.有些网址很短,有些很长.我真的不知道waht是我可能遇到的最长的URL,所以为了安全起见,我会采用一个很大的值,比如256或512.
当我定义最大字符串长度时(例如使用SQLAlchemy):
url_field = Column(String(256))
Run Code Online (Sandbox Code Playgroud)
这是否占用每行的空间(存储),即使实际的字符串更短?
我假设这与实现细节有关.我正在使用postgreSQL,但我也对sqlite,mysql感兴趣.
在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.没有空间罚款.
有关更多详细信息,请参阅有关字符数据类型的文档,以及有关如何存储它们的一些内容,请参阅特别是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 ');
Run Code Online (Sandbox Code Playgroud)
为每个col输出此查询:
SELECT 'c10', pg_column_size(c10), octet_length(c10), length(c10)
from somechars where c10 is not null;
Run Code Online (Sandbox Code Playgroud)
是:
?column? | pg_column_size | octet_length | length
c10 | 11 | 10 | 8
vc10 | 10 | 9 | 9
vc | 10 | 9 | 9
t | 10 | 9 | 9
Run Code Online (Sandbox Code Playgroud)
pg_column_size是字段中数据的磁盘大小.octet_length是没有标题的未压缩大小.length是"逻辑"字符串长度.
正如您所看到的,该char字段是填充的.如果length输入是9个字符而不是8,那么它浪费空间并且它也给出了非常令人惊讶的结果.这是因为Pg无法区分你自己放置的前导空格和它作为填充添加的前导空格之间的区别.
所以,不要使用char(n).
顺便说一句,如果我设计一个数据库中,我从来没有使用varchar(n)或char(n).我只是使用text类型并添加适当的check约束,如果有值的应用程序要求.我认为这varchar(n)在标准中有点像疣,但我认为这对于具有磁盘布局的DB很有用,其中大小限制可能会影响存储.
| 归档时间: |
|
| 查看次数: |
6328 次 |
| 最近记录: |