【问题标题】:Fillfactor for a sequential index that is PK为 PK 的顺序索引的填充因子
【发布时间】:2022-02-07 09:16:13
【问题描述】:

是的,又是fillfactor。我花了很多时间阅读,我无法决定每种情况下什么是最好的。我不明白碎片何时以及如何发生。我正在将数据库从 MS SQL Server 迁移到 PostgreSQL 9.2。

案例一

10-50 次插入/分钟顺序(串行)PK,20-50 次读取/小时。

CREATE TABLE dev_transactions (
  transaction_id serial NOT NULL,
  transaction_type smallint NOT NULL,
  moment timestamp without time zone NOT NULL,
  gateway integer NOT NULL,
  device integer NOT NULL,
  controler smallint NOT NULL,
  token integer,
  et_mode character(1),
  status smallint NOT NULL,
  CONSTRAINT pk_dev_transactions PRIMARY KEY (transaction_id)
);

案例 2

类似的结构,串行 PK 的索引,每 2 个月写入约 50.000 个寄存器的块(一次),读数为 10-50/分钟。

50% 的填充因子是否意味着每次插入都会生成一个新页面并将 50% 的现有行移动到新生成的页面?

50% 的填充因子是否意味着在新数据页的物理行之间分配了释放空间

只有在现有页面中没有剩余空间时才会生成新页面?

如你所见,我很困惑;我会很感激一些帮助——也许是阅读 PostgreSQL 和索引 fillfactor 的好链接。

【问题讨论】:

  • 你在更新桌面吗?填充因子与更新性能有关。
  • 永远不要在我想要索引的字段中,在这两种情况下都是 PK 并且插入时它永远保持相同的价值。

标签: sql postgresql database-design fillfactor


【解决方案1】:

FILLFACTOR

只有INSERTSELECT 你应该在任何地方使用FILLFACTOR100。如果您不打算与UPDATEs 一起“摆动”,那么为每个内存块留出摆动空间是没有意义的。

FILLFACTOR 背后的机制很简单。 INSERTs 仅将数据页(通常为 8 kB 块)填充到 FILLFACTOR 设置声明的百分比。此外,每当您在桌面上运行VACUUM FULLCLUSTER 时,都会重新建立每个块的相同摆动空间。理想情况下,这允许UPDATE 在同一数据页中存储新的行版本,这可以在处理大量UPDATEs 时提供显着的性能提升。与 H.O.T. 结合使用也有好处。更新。见:

如果有没有更新,不要为此浪费空间并设置FILLFACTOR = 100(这是表的默认值)。

基本信息来源:CREATE TABLECREATE INDEX 的手册。

其他优化

但你可以做别的事情 - 因为你似乎是优化的傻瓜...... :)

CREATE TABLE dev_transactions(
  transaction_id serial PRIMARY KEY
, gateway integer NOT NULL
, moment timestamp NOT NULL
, transaction_type smallint NOT NULL
, status smallint NOT NULL
, device integer NOT NULL
, controler smallint NOT NULL
, token integer
, et_mode character(1)
);

这会针对 数据对齐 优化您的表格,并避免典型 64 位服务器的 填充 并节省几个字节,平均可能只有 8 个字节 - 您通常不能用“列俄罗斯方块”挤出太多东西:

NOT NULL 列保留在表的开头以获得非常小的性能奖励。

您的表格有 9 列。这意味着扩展 NULL 位图需要额外的 8 字节 - 这将适合仅 8 列 的初始 1 字节 NULL 位图。 如果定义 et_modetoken NOT NULL,则所有列都是 NOT NULL,并且从不使用 NULL 位图,每行释放 8 个字节。
如果您不声明NOT NULL,这甚至适用于每行。如果所有列都有值,则该行没有 NULL 位图。在您的特殊情况下,这会导致矛盾效应,即填写 et_modetoken 的值可以使您的存储大小更小或至少保持不变:

基本信息来源:Database Physical Storage上的手册。

将行的大小(填充值)与原始表进行比较以获得明确的证据:

SELECT pg_column_size(t) FROM dev_transactions t;

(加上可能在行之间填充,因为下一行从 8 个字节的倍数开始。)

【讨论】:

  • @Erwin 非常感谢,这些信息非常有用,是的,我是优化的傻瓜。我会接受你的回答。如果您有一些链接让我深入了解填充因子的工作原理,我将不胜感激。
  • @HMarioD:我添加了更多解释和答案链接。
  • 谢谢,再问一个问题,我会为transaction_id添加一个索引,填充因子为100。UNIQUE关键字不是必需的,因为该字段是PK,对吧?
  • @HMarioD:整个索引 不是必需的,因为该字段是 PK - 它是通过 Postgres 中功能齐全的唯一索引实现的。你已经在这里完成了。 ;) 是的,索引会继承表的填充因子设置(除非您另外指定)。
  • 在 ms SQL Server 中不同,一个 pk 不能被认为是索引,只要我知道。再次感谢您的其他答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
相关资源
最近更新 更多