在PostgreSQL中将varchar更改为布尔值

在PostgreSQL中将varchar更改为布尔值,postgresql,database-design,query-optimization,storage,postgresql-9.1,Postgresql,Database Design,Query Optimization,Storage,Postgresql 9.1,我开始从事一个项目,其中有一个相当大的表(大约82000000行),我认为它非常臃肿。其中一个字段定义为: consistency character varying NOT NULL DEFAULT 'Y'::character varying 它用作布尔值,值应始终为('Y'|'N') 注意:没有检查约束等 我正试图找出改变这个领域的理由。以下是我所拥有的: 它被用作布尔值,所以就这样吧。显式比隐式好 它可以防止编码错误,因为现在任何可以转换成文本的东西都会被盲目地放进去 以下是我的问

我开始从事一个项目,其中有一个相当大的表(大约82000000行),我认为它非常臃肿。其中一个字段定义为:

consistency character varying NOT NULL DEFAULT 'Y'::character varying
它用作布尔值,值应始终为('Y'|'N')

注意:没有检查约束等

我正试图找出改变这个领域的理由。以下是我所拥有的:

  • 它被用作布尔值,所以就这样吧。显式比隐式好
  • 它可以防止编码错误,因为现在任何可以转换成文本的东西都会被盲目地放进去
以下是我的问题

  • 尺寸/存储空间如何?db是UTF-8。因此,我认为在这方面确实没有多少节约。在UTF-8中,
    布尔值应该是1个字节,但
    'Y'
    也应该是1个字节(至少在Python中检查长度时是这样)。这里还有其他可以节省的存储开销吗
  • 查询性能?Postgres会因为“
    =TRUE
    ”和“
    =Y”
    ”的原因而获得任何性能提升吗
PostgreSQL(与Oracle不同)拥有成熟的。通常,“是/否标志”应该是
布尔值
。这是正确的类型使用

尺寸/存储空间如何? 基本上,一列占用磁盘上的1字节
文本
字符变化时
()

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

对于简单字符,这是2个字节。所以可以将该列的存储量减半

实际存储比这更复杂。每个表都有一些固定的开销,有一些特殊的和某些类型的需求。总体影响将非常有限——如果可以察觉的话。

编码
UTF8
在这里没有任何区别。基本ASCII字符与其他编码(如
LATIN-1
)位兼容

在您的情况下,根据您的描述,您应该保持您似乎已经拥有的-独立于基类型

查询性能? 在任何情况下,使用boolean都会稍微好一点。除了稍微小一些之外,
boolean
的逻辑更简单,
varchar
text
通常还带有特定的规则。但是不要对这么简单的事情期望太高

而不是

WHERE consistency = 'Y'
你可以写:

WHERE consistency = TRUE
但是,实际上,您可以简化为:

WHERE consistency
无需进一步评估

改变类型 转换表格很简单:

ALTER TABLE tbl ALTER consistency TYPE boolean
USING CASE consistency WHEN 'Y' THEN TRUE ELSE FALSE END;

这个
大小写
表达式将所有不为
真的('Y')折叠为
假的
。NOTNULL约束保持不变。

无论是存储大小还是查询性能,从单个VARCHAR切换到布尔值都不会显著提高。虽然您是对的,当您谈论二进制值时,使用布尔值在技术上更干净,但是更改的成本可能远远高于好处。例如,如果您担心正确性,那么可以在列上进行检查

ALTER TABLE tablename ADD CONSTRAINT consistency CHECK (consistency IN ('Y', 'N'));

@DavidS注意到,通过
altertable
更改类型将在重写时独占锁定整个表。如果您负担不起,可以分步执行:
altertable
添加一个新的可空布尔字段<代码>更新
以填充该字段
altertable
使其
不为NULL
altertable
删除旧的varchar列,并
altertable
将新的布尔列重命名为varchar列的名称。您可以添加一个触发器,在重写过程中捕获新的
INSERT
s、
UPDATE
s和
DELETE
s,并确保它们也设置了新的布尔列。@CraigRinger。谢谢你的评论/建议。