我在 Postgresql 9.1 中有几百万行的大表。其中一列是带有时区的时间戳。
常用查询是使用 where 子句'column > (now()::date - 11)'
查找最近十天的数据。
我想建立一个仅适用于上个月数据的索引,以限制扫描。部分索引。
到目前为止,我还没有弄清楚如何使用上个月的实际,所以我开始硬编码“2015-12-01”作为索引的开始日期。
create index q on test (i) where i > '2015-01-01';
这工作正常,索引已创建。但不幸的是,它没有被使用,因为它把 '2015-01-01' 当作一个::timestamp
,而查询是一个::date
. 所以没有使用索引,我回到了第一方。
接下来,我尝试修改索引以将列与日期进行比较,以便匹配。但在这里,我碰到了不可变的墙。
作为可变函数to_date
,cast as date
它们依赖于本地时区,索引创建失败。
如果我有这样的测试表:
create table test (i timestamptz);
然后尝试创建索引
create index q on test (i) where i > to_date('2015-01-01','YYYY-DD-MM');
然后它失败了
ERROR: functions in index predicate must be marked IMMUTABLE
这是可以理解的。但是现在,当我尝试使用特定时区时
create index q on test (i) where i > to_date('2015-01-01','YYYY-DD-MM')
at time zone 'UTC';
它仍然失败
ERROR: functions in index predicate must be marked IMMUTABLE
这我不明白了。它定义了时区。还有什么是不可变的?
我也尝试自己创建不可变函数:
CREATE FUNCTION
datacube=# create or replace function immutable_date(timestamptz) returns date as $$
select ($1::date at time zone 'UTC')::date;
$$ language sql immutable;
但是在索引中使用这个函数:
create index q on test (i) where i > immutable_date('2015-01-01');
失败并出现相同的错误:
ERROR: functions in index predicate must be marked IMMUTABLE
我在这里不知所措。也许它与语言环境有关,而不仅仅是时区?或者其他什么使它可变?
而且 - 也许还有另一种更简单的方法,将索引限制为上一两个月的数据?Postgres 中的表分区需要重建整个数据库,到目前为止我还没有找到其他任何东西。