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

时间:2015-04-20 20:06:41

标签: postgresql jsonb

我有一个关于PostgreSQL的表,其中一个名为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

我已经尝试过这样做了#34; inmutable"使用

设置时区

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

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

1 个答案:

答案 0 :(得分:6)

这个表达式不允许在索引中使用:

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

它不是一成不变的,因为第一次演员取决于你的DateStyle设置(以及其他内容)。在函数调用之后将结果转换为UTC 没有帮助,不确定性已经悄悄进入......

解决方案通过修复时区(例如@a_horse already hinted)使使转换为不可变的函数。

我建议使用to_timestamp()代替演员(也不是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'));

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

相关: