【问题标题】:Postgresql: In-Row vs Out-of-Row for text/varcharPostgresql:文本/varchar 的行内与行外
【发布时间】:2015-07-30 13:04:17
【问题描述】:

两部分问题:

  1. 在行内存储文本/varchars 的 Postgresql 行为是什么? 行外?我是否正确地认为使用默认设置,所有列将始终存储在行中,直到达到 2kB 大小?

  2. 我们是否可以控制上述行为?有什么方法可以更改特定列/表的阈值,或强制特定列始终存储在行外?

我已经阅读了 PostGresql Toast 文档 (http://www.postgresql.org/docs/8.3/static/storage-toast.html),但我没有看到任何更改阈值的选项(默认值似乎是 2kB-for-row)或强制列始终存储输出- of-row(EXTERNAL 只允许它,但不强制它)。

我找到了解释如何在 SQL Server (https://msdn.microsoft.com/en-us/library/ms173530.aspx) 上执行此操作的文档,但没有看到 PostGresql 的任何类似内容。


如果有人对我的动机感兴趣,我有一个表,其中混合了短一致性列(ID、时间戳等)、一个 varchar(200) 列和一个 text/varchar(max) 列,它的长度可能非常大。我目前将两个 varchars 都存储在一个单独的表中,只是为了允许对短一致的列进行有效的存储/查找/扫描。

然而,这很痛苦,因为我必须经常进行连接才能读取所有数据。我真的很想将上述所有字段存储在同一个表中,并告诉 Postgresql 始终强制将 2 个 VARCHAR 存储在行外。

【问题讨论】:

    标签: sql database postgresql text varchar


    【解决方案1】:

    已编辑答案

    对于问题的第一部分:你是对的(例如参见this)。

    对于问题的第二部分:存储列的标准方法是,如果可变长度文本字段大小超过 2KB,则压缩它们,并最终将它们存储到一个单独的区域,称为“TOAST 表”。

    您可以通过对列使用以下命令向系统提供有关如何存储字段的“提示”:

    ALTER TABLE YourTable
      ALTER COLUMN YourColumn SET STORAGE (PLAIN | EXTENDED | EXTERNAL | MAIN)
    

    来自manual

    SET STORAGE

    此表单设置列的存储模式。这控制此列是内联保存还是保存在辅助 TOAST 表中,以及是否应压缩数据。 PLAIN 必须用于整数等固定长度值,并且是内联的、未压缩的。 MAIN 用于内联、可压缩的数据。 EXTERNAL 用于外部未压缩数据,EXTENDED 用于外部压缩数据。 EXTENDED 是大多数支持非 PLAIN 存储的数据类型的默认值。使用EXTERNAL 将使对非常大的文本和bytea 值的子字符串操作运行得更快,但会增加存储空间。请注意,SET STORAGE 本身不会更改表中的任何内容,它只是设置在未来表更新期间要采用的策略。有关详细信息,请参阅第 59.2 节。

    由于手册在这一点上没有完全明确,这是我的解释:在任何情况下,关于如何存储字段的最终决定都留给系统,考虑到以下限制:

    1. 不能存储任何字段以使行的总大小超过 8KB
    2. 如果字段的大小小于 TOAST_TUPLE_THRESHOLD
    3. 满足前一个后 约束,系统试图满足SET STORAGE 策略 由用户指定。如果没有指定存储策略,每个 TOAST-able 字段自动声明为EXTENDED

    在这些假设下,确保所有列的值都存储在行外的唯一方法是使用小于最小值的TOAST_TUPLE_THRESHOLD 值重新编译系统列的任何值的大小。

    【讨论】:

    • 根据以下(postgresql.org/docs/9.4/static/storage-toast.html):只有当要存储在表中的行值大于 TOAST_TUPLE_THRESHOLD 字节(通常为 2 kB)时,才会触发 TOAST 代码。 EXTENDED 允许压缩和离线存储。这是大多数支持 TOAST 的数据类型的默认值。将首先尝试压缩,然后如果行仍然太大,则进行外联存储。这似乎意味着该列将被存储在行外,只有当它超过 ~2kB 时。有什么办法可以强制它总是在行外存储?
    • 您引用的页面中描述的行为是PostgreSQL的自动行为。我在答案中建议的策略 强制 系统遵循您想要的存储策略(例如,参见 discussion)。唯一的另一种可能性是重新编译 PostgreSQL 的私有副本以更改参数TOAST_TUPLE_THRESHOLD,但这只是最后的手段。请注意,如果您应用 ALTER COLUMN 解决方案,则必须重新加载表(阅读手册!)。
    • 您确定ALTER COLUMN SET STORAGE EXTENDED 强制系统将数据存储在行外吗?根据手册:EXTENDED is for external, compressed data. EXTENDED is the default for most data types that support non-PLAIN storage 即,扩展 已经 是 varchar(max) 的默认值,所以我没想到命令会做任何事情。同一部分也将我们引向 58.2,其中指出 strategies for storing TOAST-able columns: Extended...Compression will be attempted first, then out-of-line storage if the row is still too big.
    猜你喜欢
    • 2013-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    • 2012-09-27
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    相关资源
    最近更新 更多