7

我在 PostgreSQL 上有一个表,其中有一个名为的字段datajsonb其中包含很多对象,我想创建一个索引来加快查询速度。我使用几行来测试数据(只有 15 行),但我不想在将来遇到查询问题。我从 Twitter API 获取数据,所以一周后我得到了大约 10gb 的数据。
如果我做正常的索引

CREATE INDEX ON tweet((data->>'created_at'));

我得到一个文本索引,如果我做:

Create index on tweet((CAST(data->>'created_at' AS timestamp)));

我明白了

ERROR: functions in index expression must be marked IMMUTABLE

我试图让它“不可变”设置时区

date_trunc('seconds', CAST(data->>'created_at' AS timestamp) at time zone 'GMT')

但我仍然收到“不可变”错误。那么,如何从 JSON 中完成时间戳索引?我知道我可以用日期制作一个简单的列,因为它可能会在一段时间内保持不变,但我想学习如何做到这一点。

4

1 回答 1

13

索引中也不允许此表达式:

(CAST(data->>'created_at' AS timestamp) at time zone 'UTC')

它不是一成不变的,因为第一个演员取决于您的DateStyle设置(除其他外)。在函数调用后将结果转换为 UTC 无济于事,不确定性已经潜入......

解决方案是通过固定时区使演员表不可变的函数(如@a_horse已经暗示)。

我建议使用to_timestamp()(这也是 only STABLE, not IMMUTABLE)而不是演员来排除一些麻烦的来源 -DateStyle成为一个。

CREATE OR REPLACE FUNCTION f_cast_isots(text)
  RETURNS timestamptz AS
$$SELECT to_timestamp($1, 'YYYY-MM-DD HH24:MI')$$  -- adapt to your needs
  LANGUAGE sql IMMUTABLE;

请注意,这将返回timestamptz. 然后:

CREATE INDEX foo ON t (f_cast_isots(data->>'created_at'));

此相关答案中对此技术的详细说明:

有关的:

于 2015-04-21T02:47:38.530 回答