1

我正在对我们项目中最大的表之一进行性能调整。在阅读索引时,我遇到了 PostgreSQL 中的部分索引。将索引仅放在经常访问的行上听起来是一个非常好的主意。

不过,我无法弄清楚部分索引是如何更新的。例如,我有一个包含以下列的表:

task_uuid, job_id, enqueued_at, updated_at, task_status

task_status= ENQUEUED, RUNNING, ASSIGNED, FAILED

ENQUEUED我们非常频繁地搜索处于状态的记录。如果我们在其上添加部分索引,(task_uuid, task_status)将构建一个唯一键并提高性能。但是,我想知道,当我们更新记录RUNNING状态时,记录更新时会发生什么。(task_uuid, task_status)仍然是唯一的,但它会从部分索引中删除吗?因为记录不符合条件。

4

1 回答 1

2

如果我们在 (task_uuid, task_status) 上添加部分索引,它将构建一个唯一键并提高性能。

如果您在索引的定义中指定它,它只会将其构建为唯一的。否则它将不是唯一索引,即使这些列恰好是唯一的。

当记录被更新以使其不再匹配索引的 WHERE 谓词时,索引不会发生任何事情。它仍然有一个指向行的指针,它只是指向不再有效的东西。如果您确实将索引指定为 UNIQUE,那么在插入冲突的索引元组时,它将跟随旧元组的指针指向表,意识到它是无效的,并允许继续插入。

下次清空表时,将清理那些过时的指针。带有部分索引的队列表通常应该经常被清理(比默认更频繁),因为索引很容易膨胀。Autovac 设置取决于废弃的表行的比例,而不是废弃的索引行的比例。对于部分索引,这些分数不相同。(另一方面,您似乎没有“COMPLETED”的状态。如果立即删除已完成的任务,则队列表可能会保持足够小,这无关紧要。)

此外,当索引扫描跟随从索引到表的指针并发现该行不再对任何人可见时,它会将索引条目标记为已死。这样以后的索引扫描就不必毫无意义地跳到表上。但是这种“微真空”只发生在常规索引扫描中,而不是位图扫描,而且它只发生在主服务器上完成的查询,而不是仅仅在热备用上完成的任何查询。

于 2020-08-10T14:36:41.570 回答