在PostgreSQL中将varchar更改为布尔值
我开始从事一个项目,其中有一个相当大的表(大约82000000行),我认为它非常臃肿。其中一个字段定义为:在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') 注意:没有检查约束等 我正试图找出改变这个领域的理由。以下是我所拥有的: 它被用作布尔值,所以就这样吧。显式比隐式好 它可以防止编码错误,因为现在任何可以转换成文本的东西都会被盲目地放进去 以下是我的问
consistency character varying NOT NULL DEFAULT 'Y'::character varying
它用作布尔值,值应始终为('Y'|'N')
注意:没有检查约束等
我正试图找出改变这个领域的理由。以下是我所拥有的:
- 它被用作布尔值,所以就这样吧。显式比隐式好
- 它可以防止编码错误,因为现在任何可以转换成文本的东西都会被盲目地放进去
- 尺寸/存储空间如何?db是UTF-8。因此,我认为在这方面确实没有多少节约。在UTF-8中,
布尔值应该是1个字节,但
也应该是1个字节(至少在Python中检查长度时是这样)。这里还有其他可以节省的存储开销吗'Y'
- 查询性能?Postgres会因为“
”和“=TRUE
”的原因而获得任何性能提升吗=Y”
布尔值
。这是正确的类型使用
尺寸/存储空间如何?
基本上,一列占用磁盘上的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。谢谢你的评论/建议。