在 PostgreSQL 上从 JSON 创建时间戳索引

Create timestamp index from JSON on PostgreSQL

我在 PostgreSQL 上有一个 table,其中有一个名为 data 的字段 jsonb,其中包含很多对象,我想创建一个索引来加快查询速度。我使用几行来测试数据(只有 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

我已经尝试 "inmutable" 设置时区

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

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

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

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

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

解决方案是一个函数,通过固定时区(如使转换不可变。

我建议使用 to_timestamp()(也只是 STABLE,而不是 IMMUTABLE)而不是强制转换以排除一些麻烦源 - DateStyle一.

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

注意这个returnstimestamptz。那么:

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

此相关答案中对此技术的详细解释:

  • Does PostgreSQL support "accent insensitive" collations?

相关:

  • Query on a time range ignoring the date of timestamps