AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 286640
Accepted
ldrg
ldrg
Asked: 2021-03-08 14:41:46 +0800 CST2021-03-08 14:41:46 +0800 CST 2021-03-08 14:41:46 +0800 CST

PostgreSQL 表的优化列顺序是否总是在末尾具有可变长度类型?

  • 772

有一篇流行且看似权威的博客文章On Rocks and Sand关于如何优化 PostgreSQL 表的大小以通过重新排序列长度来消除内部填充。他们解释了如果可变长度类型不在表格末尾,它们如何产生一些额外的填充:

这意味着我们可以整天链接可变长度的列,而无需在右侧边界处引入填充。因此,我们可以推断出可变长度列不会引入膨胀,只要它们位于列列表的末尾。

在文章的最后,总结一下:

按照 pg_type 中定义的类型长度对列进行排序。

有一个与 Ruby 的 ActiveRecord 集成的库,可以自动重新排序列以减少填充,称为pg_column_byte_packer。您可以在该 repo 中看到 README 引用了上述博客文章,并且通常与博客文章描述的内容相同。

但是,pg_column_byte_packer返回的结果与它引用的博客文章不一致。这篇博文取自 PostgreSQL 的内部pg_type.typelen,它通过 -1 的对齐方式将可变长度列始终放在末尾。pg_column_byte_packer给他们一个对齐3。

pg_column_byte_packer有解释性评论:

    # These types generally have an alignment of 4 (as designated by pg_type
    # having a typalign value of 'i', but they're special in that small values
    # have an optimized storage layout. Beyond the optimized storage layout, though,
    # these small values also are not required to respect the alignment the type
    # would otherwise have. Specifically, values with a size of at most 127 bytes
    # aren't aligned. That 127 byte cap, however, includes an overhead byte to store
    # the length, and so in reality the max is 126 bytes. Interestingly TOASTable
    # values are also treated that way, but we don't have a good way of knowing which
    # values those will be.
    #
    # See: `fill_val()` in src/backend/access/common/heaptuple.c (in the conditional
    # `else if (att->attlen == -1)` branch.
    #
    # When no limit modifier has been applied we don't have a good heuristic for
    # determining which columns are likely to be long or short, so we currently
    # just slot them all after the columns we believe will always be long.

评论似乎没有错,因为文本列的 apg_type.typalign值为 4,但它们也有pg_type.typlen-1 的值,博客文章认为在表格末尾时获得最佳包装。

因此,对于具有一integer列、一text列和一smallint列的表,pg_column_byte_packer会将文本列放在两者之间。他们甚至有一个单元测试来断言这种情况总是会发生。

我的问题是:什么列的顺序实际上是为最小的空间打包的?来自的评论pg_column_byte_packer似乎没有错,因为文本列的 apg_type.typalign值为 4,但它们的 apg_type.typlen值为 -1。

postgresql
  • 1 1 个回答
  • 240 Views

1 个回答

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2021-03-08T16:58:55+08:002021-03-08T16:58:55+08:00

    来自的评论pg_column_byte_packer似乎没有错,因为文本列的 apg_type.typalign值为 4,但它们的 apg_type.typlen值为 -1。

    当我几年前研究它时,我也感到困惑。typlen = -1只是表示varlena存储,名义上具有typalign = 'i'(整数对齐,需要从4字节偏移开始)。但这还不是全部。最终,我在源代码的注释中找到了解释:

    另请注意,我们允许在存储“打包”varlenas 时违反名义对齐;TOAST 机制负责从大多数代码中隐藏它。

    因此,varlena数据 < 127 字节(在可能的压缩之后)仅增加 1 字节的开销(表示其长度)并且不需要“磁盘上”的对齐填充。(这些天几乎没有任何“磁盘”了。)

    看:

    • 在 PostgreSQL 中计算和节省空间(我在这里创造了术语“列俄罗斯方块”)

    要回答标题中的问题:

    PostgreSQL 表的优化列顺序是否总是在末尾具有可变长度类型?

    真实的。超过 127 字节的数据不能以优化的形式存储,并退回到需要“整数对齐”。如果我们不知道 varlena 类型的列将保持在该阈值以下(大部分时间),我们不能肯定地说。

    此外,优化存储还有其他注意事项。一行中有许多列,首先使用NOT NULL固定大小长度的列计算元组存储偏移量会更便宜。首先放置经常访问的列也产生了一个微小的优势。所有这些都因 TOAST 机制和 index(-only) 访问而变得更加复杂。

    但所有这些影响通常都很微小。相比之下,当一列占用 200 个字节时,对齐填充丢失 3 个字节就显得相形见绌了。所以大多不值得费心。经验法则涵盖了大部分内容:

    按所需的对齐方式对列进行排序typalign:
    d--> i--> s--> c。
    但是typlen = -1("varlena") 最后(通常),即使是正式typalign = 'i'的 .

    手册:

    c = char alignment, i.e., no alignment needed.
    s = short alignment (2 bytes on most machines).
    i = int alignment (4 bytes on most machines).
    d = double alignment (8 bytes on many machines, but by no means all).
    

    你的例子

    因此,对于具有一integer列、一text列和一smallint列的表,pg_column_byte_packer会将文本列放在两者之间。

    pg_column_byte_packer名副其实。int--> text-->smallint尽可能地紧。

    对于短字符串的典型情况,唯一相关的决定是int放在第一位。smallint最多可以在奇数字节偏移处强制 1 个额外字节的对齐填充。由于元组空间总是以 8 字节的倍数分配,这永远不会导致更大的元组。

    超过磁盘上 127 字节阈值的字符串(包括 1 个前导长度字节),翻转到 4 个前导长度字节并需要标称integer对齐。这就是放在textbeforesmallint可以有效地保护 8 个字节的地方。随机字符串长度发生在 25% 的情况下,因此对于至少 144 个字节的元组,平均 2 个字节。

    就是这样。但是放在第smallint一个通常具有微小的优势,并且大多数text列都远低于长度阈值。

    要记住的是不要穿插多个smallint和text列。在这种情况下,可以叠加多个偏移量。

    • 2

相关问题

  • 我可以在使用数据库后激活 PITR 吗?

  • 运行时间偏移延迟复制的最佳实践

  • 存储过程可以防止 SQL 注入吗?

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve