如何在 Postgres 中为过去 90 天的记录创建索引使 now() 不可变
How to create index on records for last 90 days in Postgres Making now() immutable
我有一个案例,由于速度问题,我只想为过去 90 天的记录创建索引。
当我尝试创建这样的索引时:
create index if not exists idx_d1_section_learner_partial_date_modified
on instruct.d1_section_learner (audit_modified_datetime)
where (audit_modified_datetime >= '2019-07-01 00:00:00'::timestamp);
它有效,但我想保持这种动态,所以我尝试了这个:
create index if not exists idx_d1_section_learner_partial_date_modified
on instruct.d1_section_learner (audit_modified_datetime)
where (audit_modified_datetime >= now() - interval '90 days'::timestamp);
给出错误:
ERROR: functions in index predicate must be marked IMMUTABLE
我知道这是因为当前的时间戳。因为它在交易中不是恒定的。有什么办法可以避免这种情况吗?
或者我可以将 current_timestamp
标记为不可变的吗?
而不是不可变的 now()
函数(这是行不通的!)使用返回 timestamp
常量的伪不可变函数,并将您的部分索引基于它 - 以及您的应该使用它的查询。
此外,您不必必须每天更新索引。该索引可以包含几个过时的行,这几乎无关紧要。您只需向查询添加 exact 条件 additionally。随着添加更多行,性能会随着时间的推移 缓慢 下降。时不时重新创建函数和索引就足够了。可以是每周一次,有时数据库负载最低。
刚好我在6年前发了一个完整的解决方案:
- Optimize performance for queries on recent rows of a large table
对其进行了一些更新以反映最近的发展。
旁白:now()
returns timestamptz
,而不是 timestamp
。 LOCALTIMESTAMP
会更合适。但是不要去那里。
我有一个案例,由于速度问题,我只想为过去 90 天的记录创建索引。
当我尝试创建这样的索引时:
create index if not exists idx_d1_section_learner_partial_date_modified
on instruct.d1_section_learner (audit_modified_datetime)
where (audit_modified_datetime >= '2019-07-01 00:00:00'::timestamp);
它有效,但我想保持这种动态,所以我尝试了这个:
create index if not exists idx_d1_section_learner_partial_date_modified
on instruct.d1_section_learner (audit_modified_datetime)
where (audit_modified_datetime >= now() - interval '90 days'::timestamp);
给出错误:
ERROR: functions in index predicate must be marked IMMUTABLE
我知道这是因为当前的时间戳。因为它在交易中不是恒定的。有什么办法可以避免这种情况吗?
或者我可以将 current_timestamp
标记为不可变的吗?
而不是不可变的 now()
函数(这是行不通的!)使用返回 timestamp
常量的伪不可变函数,并将您的部分索引基于它 - 以及您的应该使用它的查询。
此外,您不必必须每天更新索引。该索引可以包含几个过时的行,这几乎无关紧要。您只需向查询添加 exact 条件 additionally。随着添加更多行,性能会随着时间的推移 缓慢 下降。时不时重新创建函数和索引就足够了。可以是每周一次,有时数据库负载最低。
刚好我在6年前发了一个完整的解决方案:
- Optimize performance for queries on recent rows of a large table
对其进行了一些更新以反映最近的发展。
旁白:now()
returns timestamptz
,而不是 timestamp
。 LOCALTIMESTAMP
会更合适。但是不要去那里。