在PostgreSQL中将varchar更改为boolean

Dav*_*d S 12 postgresql storage database-design query-optimization postgresql-9.1

我已经开始研究一个项目,那里有一个相当大的表(大约82,000,000行),我觉得它非常臃肿.其中一个字段定义为:

consistency character varying NOT NULL DEFAULT 'Y'::character varying
Run Code Online (Sandbox Code Playgroud)

它用作布尔值,值应始终为('Y'|'N').

注意:没有检查约束等.

我试图找出理由改变这个领域的理由.这是我有的:

  • 它被用作布尔值,所以就这样吧.显式优于隐式.
  • 它将防止编码错误,因为现在任何可以转换为文本的内容都会在那里盲目进行.

这是我的问题.

  • 尺寸/存储怎么样?db是UTF-8.所以,我认为在这方面确实没有多少节省.对于a boolean,它应该是1个字节,而对于'Y'UTF-8中的a 应该是1个字节(至少这是我在Python中检查长度时得到的).这里是否还有其他存储空间可以保存?
  • 查询性能?Postgres会因" =TRUE"与" ='Y'"的原因而获得任何性能提升吗?

Erw*_*ter 21

PostgreSQL(与Oracle不同)具有完全成熟的boolean类型.通常,应该是"是/否标志" boolean.这是正确的使用类型!

尺寸/存储怎么样?

基本上,一boolean列占用磁盘上的1个字节,
textcharacter varying(在这里引用手册)......

短字符串(最多126个字节)的存储要求是1个字节加上实际的字符串

这是简单字符的2个字节.因此,您可以将该列的存储减半.

实际存储比这更复杂.每个表,页面和行有一些固定的开销,有特殊的NULL存储空间,有些类型需要数据对齐.整体影响将非常有限 - 如果有明显的话.
更多关于如何衡量实际空间需求的信息.

编码UTF8在这里没有任何区别.基本的ASCII字符与其他编码类比特兼容LATIN-1.

在您的情况下,根据您的描述,您应该保留您似乎已经拥有的NOT NULL约束 - 独立于基本类型.

查询性能?

在任何情况下使用布尔值都会略胜一筹.除了稍微小一点之外,逻辑boolean更简单,varchar或者text通常还有COLLATION特定规则.但对于那些简单的事情,不要指望太多.

代替

WHERE consistency = 'Y'
Run Code Online (Sandbox Code Playgroud)

你可以写:

WHERE consistency = TRUE
Run Code Online (Sandbox Code Playgroud)

但是,实际上,您可以简化为:

WHERE consistency
Run Code Online (Sandbox Code Playgroud)

无需进一步评估.

改变类型

转换你的表很简单:

ALTER TABLE tbl ALTER consistency TYPE boolean
USING CASE consistency WHEN 'Y' THEN TRUE ELSE FALSE END;
Run Code Online (Sandbox Code Playgroud)

CASE表达式将所有不是TRUE('Y')的内容折叠起来FALSE.NOT NULL约束只是保留.

  • @DavidS请注意,通过`ALTER TABLE`更改类型将在重写时独占锁定整个表.如果你负担不起,你可以分步执行:`ALTER TABLE`添加一个新的可以为空的布尔字段; `UPDATE`填充该字段; `ALTER TABLE`使其成为'NOT NULL`,`ALTER TABLE`删除旧的varchar列,使用`ALTER TABLE`将新的boolean列重命名为varchar列的名称.您可以添加一个触发器,在重写正在进行时捕获新的"INSERT","UPDATE"和"DELETE",并确保它们也设置了新的布尔列. (3认同)