强制更新索引

Force index to be updated

我将所有权作为 "Project -> Ownership -> User" 关系处理,以下函数获取项目所有者的名称作为文本:

CREATE FUNCTION owners_as_text(projects) RETURNS TEXT AS $$
  SELECT trim(both concat_ws(' ', screen_name, first_name, last_name)) FROM users
    INNER JOIN ownerships ON users.id = ownerships.user_id
    WHERE deleted_at IS NULL AND ownable_id = .id AND ownable_type = 'Project'
$$ LANGUAGE SQL IMMUTABLE SET search_path = public, pg_temp;

这随后用于构建忽略重音符号的索引:

CREATE INDEX index_projects_on_owners_as_text
  ON projects
  USING GIN(immutable_unaccent(owners_as_text(projects)) gin_trgm_ops)

更新项目时,也会更新此索引。然而,当例如所有者名称更改,该索引不会被触及,对吗?

在这种情况下,如何强制定期更新索引以赶上进度?

REINDEX 不是一个选项,因为它是锁定的,如果写入操作同时发生,将导致死锁。)

这个想法是错误的假设,因为索引是建立在一个实际上不是不可变的函数之上的。对于文档:

IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list.

您现在面临的问题源于不正确的假设。

由于您通过说函数是 IMMUTABLE 而实际上是 STABLE 来欺骗 PostgreSQL,因此当数据库更改时索引损坏也就不足为奇了。

解决方法是创建这样的索引。

最好不要使用该功能,而是将要搜索的表达式作为列的视图。然后可以优化使用视图的查询,可以使用immutable_unaccent(btrim(concat_ws(' ', screen_name, first_name, last_name)))上的索引。

欺骗unaccent的波动性可能是可以的...