25

CREATE TABLE在 Postgres 中,语句中列的顺序会影响性能吗?考虑以下两种情况:

CREATE TABLE foo (
  a      TEXT, 
  B      VARCHAR(512),
  pkey   INTEGER PRIMARY KEY,
  bar_fk INTEGER REFERENCES bar(pkey),
  C      bytea
); 

对比

CREATE TABLE foo2 (
  pkey   INTEGER PRIMARY KEY,
  bar_fk INTEGER REFERENCES bar(pkey),
  B      VARCHAR(512),      
  a      TEXT, 
  C      bytea
);

性能foo2会比foo列的更好的字节对齐更好吗?当 Postgres 执行时CREATE TABLE,它是按照指定的列顺序还是按照字节对齐或性能的最佳顺序重新组织列?

4

2 回答 2

27

问题 1

的性能foo2会比foo列的更好的字节对齐更好吗?

是的,列的顺序对性能的影响很小。类型对齐是更重要的因素,因为它会影响磁盘占用空间。您可以最小化存储大小(播放“俄罗斯方块”)并在数据页上压缩更多行——这是提高速度的最重要因素。

通常不值得打扰。使用这个相关答案中的极端示例,您会得到很大的不同:

类型对齐详细信息:

另一个因素是,如果您首先有固定大小的列,则检索列值会稍微快一些。我在这里引用手册

要读取数据,您需要依次检查每个属性。首先根据空位图检查该字段是否为NULL。如果是,请转到下一个。然后确保你有正确的对齐方式。如果该字段是一个固定宽度的字段,那么所有的字节都被简单地放置。如果它是一个可变长度字段(attlen = -1),那么它会更复杂一些。所有变长数据类型共享一个共同的头结构struct varlena,它包括存储值的总长度和一些标志位。

有一个开放的TODO 项允许对 Postgres Wiki 中的列位置重新排序,部分原因是这些原因。

问题2

当 Postgres 执行时CREATE TABLE,它是否遵循指定的列顺序,还是以字节对齐或性能的最佳顺序重新组织列?

按定义的顺序存储,系统不会尝试优化。

我看不到列顺序与TOAST 表的任何相关性,就像另一个答案似乎暗示的那样。

于 2012-09-26T18:21:20.280 回答
4

据我了解,PostgreSQL 在保存记录时遵循您输入列的顺序。这是否会影响性能是值得商榷的。PostgreSQL 将所有表数据存储在每个大小为 8kb 的页面中。8kb 是默认值,但可以在编译时更改。

表中的每一行都将占用页面内的空间。由于您的表定义包含可变列,因此页面可以包含可变数量的记录。您要做的是确保您可以将尽可能多的记录放入一页中。这就是为什么当表具有大量列或列大小很大时,您会注意到性能下降的原因。

话虽如此,声明 varchar(8192) 并不意味着页面将被一条记录填满,但声明 CHAR(8192) 将用完一整页,而与列中的数据量无关。

在声明 TEXT 列等 TOASTable 类型时,还需要考虑一件事。这些是可能超过最大页面大小的列。具有 TOASTable 列的表将具有关联的 TOAST 表来存储数据,并且只有指向数据的指针与表一起存储。这可能会影响性能,但可以通过 TOASTable 列上的适当索引来改善。

最后,我不得不说,列的顺序对表的性能没有太大的影响。大多数查询使用单独存储的索引来检索记录,因此列顺序被否定。它归结为需要读取多少页才能检索数据。

于 2012-09-26T16:15:03.157 回答