【问题标题】:Index on Timestamp: Functions in index expression must be marked as IMMUTABLE时间戳索引:索引表达式中的函数必须标记为 IMMUTABLE
【发布时间】:2016-01-23 18:19:37
【问题描述】:

我想在我的表上为 start_time 创建一个索引,这是一个名为 match 的 json 列中的 timestamptz(带时区的时间戳)字段。

关注this questionthis article 我知道由于时区和本地化不同,您无法在timestamptz 字段上创建索引。这两个都表明你可以在时间戳上创建索引(转换为文本),所以我尝试了以下功能:

CREATE OR REPLACE FUNCTION to_text(timestamptz) 
 RETURNS text AS $$
  SELECT to_char($1 at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
  $$
LANGUAGE sql
IMMUTABLE;

我认为这与时区和本地化没有问题。

CREATE INDEX i_match_start_time ON matches (to_text(((match->>'start_time')::timestamptz)));

这将返回以下内容:

ERROR: functions in index expression must be marked IMMUTABLE

我也尝试过返回时间戳的函数:

SELECT ($1 at time zone 'UTC') 

以及返回 unix 时间的函数(尝试双精度并转换为十进制):

SELECT EXTRACT(EPOCH FROM $1)

每个都返回相同的错误。

我需要在 start_time 上建立索引,因为几乎所有对该表的选择查询都将按 start_time 排序。

感谢您的帮助。

【问题讨论】:

  • to_text() 可能是不可变的,但 to_text(((match->>'start_time')::timestamptz)) 不是
  • @a_horse_with_no_name 你能解释一下为什么吗?我该如何解决?

标签: sql postgresql


【解决方案1】:

首先我认为这可能是CREATE INDEX 逻辑中的错误。但关键是从texttimestamptz 的演员表本身也不是IMMUTABLE。这取决于 datestyle 等易失性设置。

在您的特定情况下,有一个比您尝试过的更好的解决方法。将演员表移到函数中:

CREATE OR REPLACE FUNCTION to_text(text) 
  RETURNS text AS
$func$
SELECT to_char($1::timestamptz AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
$func$ LANGUAGE sql IMMUTABLE;

同样高效,但现在CREATE INDEX 不会吐了:

CREATE INDEX bar ON foo(to_text(j->>'start_time'));

显然,您必须相应地调整函数调用:从表达式中删除强制转换 ::timestamptz。确保您在所有地方使用相同的设置,否则索引可能会导致错误的结果。

更好

使用带有to_timestamp() 的实际不可变表达式而不是强制转换(如果您的输入模式允许的话):

CREATE OR REPLACE FUNCTION to_text(text) 
  RETURNS text AS
$func$
SELECT to_char(to_timestamp($1, 'YYYY-MM-DD"T"HH24:MI:SS.US')  -- adapt to your pattern
            AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
$func$ LANGUAGE sql IMMUTABLE;

但是请注意(引用我的测试中的错误消息):

to_date 不支持“TZ”/“tz”/“OF”格式模式

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 2015-01-26
    • 2018-10-07
    相关资源
    最近更新 更多