强制索引要更新

时间:2019-01-25 15:07:24

标签: postgresql database-indexes functional-index

我将所有权作为“项目->所有权->用户”关系进行处理,以下功能将项目所有者的名称显示为文本:

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 = $1.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是不可选项,因为它已锁定,如果同时执行写操作,将导致死锁。)

2 个答案:

答案 0 :(得分:1)

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

  

IMMUTABLE表示该函数无法修改数据库,并且在给定相同的参数值时始终返回相同的结果;也就是说,它不会执行数据库查找或以其他方式使用其参数列表中未直接显示的信息。

您现在面临的问题来自错误的假设。

答案 1 :(得分:0)

由于您对PostgreSQL撒谎是说该函数实际上是IMMUTABLE时是STABLE,所以在数据库更改时索引损坏就不足为奇了。

解决方案不是创建这样的索引的

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

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