【问题标题】:Change varchar to boolean in PostgreSQL在 PostgreSQL 中将 varchar 更改为布尔值
【发布时间】:2012-10-01 05:13:45
【问题描述】:

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

consistency character varying NOT NULL DEFAULT 'Y'::character varying

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

注意:没有检查约束等。

我正在尝试找出理由来证明更改此字段的合理性。这是我所拥有的:

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

这是我的问题。

  • 大小/存储怎么样?数据库是 UTF-8。所以,我认为在这方面确实没有多少节省。 boolean 应该是 1 个字节,但 UTF-8 中 'Y' 应该是 1 个字节(至少当我在 Python 中检查长度时我得到的结果)。这里是否还有其他可以节省的存储开销?
  • 查询性能? Postgres 是否会因“=TRUE”与“='Y'”的原因而获得任何性能提升?

【问题讨论】:

    标签: postgresql database-design query-optimization storage postgresql-9.1


    【解决方案1】:

    PostgreSQL(与 Oracle 不同)有一个成熟的 boolean type。通常,“是/否标志”应该是boolean。这是正确使用的类型!

    大小/存储怎么样?

    基本上,boolean 列在磁盘上占用 1 个字节
    textcharacter varying (quoting the manual here) ...

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

    对于简单字符,这是 2 个字节。因此,您可以将 该列的存储空间减半。

    实际存储比这更复杂。每个表有一些固定开销page and row,有特殊的NULL storage,有些类型需要data alignment。整体影响将非常有限 - 如果能引起注意的话。
    More on how to measure actual space requirement.

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

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

    查询性能?

    在任何情况下使用布尔值都会稍微好一些。除了略小之外,boolean 的逻辑更简单,varchartext 通常也带有COLLATION 特定规则。但不要对这么简单的事情抱太大期望。

    代替

    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;
    

    这个CASE 表达式将所有不是TRUE ('Y') 的东西折叠成FALSE。 NOT NULL 约束保持不变。

    【讨论】:

    • @DavidS 请注意,通过ALTER TABLE 更改类型将在重写时独占锁定整个表。如果您负担不起,您可以分步进行:ALTER TABLE 添加一个新的可为空的布尔字段; UPDATE 填充该字段; ALTER TABLE 使 NOT NULLALTER TABLE 删除旧的 varchar 列,ALTER TABLE 将新的布尔列重命名为 varchar 列的名称。您可以添加一个触发器,在重写过程中捕获新的INSERTs、UPDATEs 和DELETEs,并确保它们也设置了新的布尔值。
    • @CraigRinger。感谢您的评论/建议。
    【解决方案2】:

    从单个 VARCHAR 切换到 BOOLEAN,存储大小和查询性能都不会显着提高。尽管您是对的,当您谈论二进制值时使用布尔值在技术上更清洁,但更改的成本可能远高于收益。如果您担心正确性,则可以检查列,例如

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-17
      • 2023-02-08
      • 2019-03-20
      • 2016-10-07
      • 2015-09-29
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      相关资源
      最近更新 更多