Postgres JSONB-子对象的所有动态(整数)属性的索引

时间:2018-07-29 05:58:10

标签: postgresql jsonb

我的数据库中有一个JSONB表,如下所示:

             data
-------------------------------
{
  "nestedObject": {
    "dynamic-key-1": 123,
    "dynamic-key-2": 456,
    "dynamic-key-3": 789,
    "and so on": 123
  },
  "rest of object": "goes here"
}
-- a few million more objects come here

我特别想知道是否可以对data->'nestedObject' 所有(现有)键进行索引作为整数。目前(据我了解)。我知道,如果我提前知道按键,我可以做类似的事情

CREATE INDEX IF NOT EXISTS idx_gin_my_jsonb_integer_index ON table 
    USING BTREE (((data->'nestedObject'->>'integerKey')::integer));

但是不幸的是,这是不可能的,因为我不提前知道键(嵌套对象的属性是在运行时基于时间戳等生成的)。许多nestedObject可能具有相同的密钥(例如,许多对象可能具有data->'nestedObject'->'dynamic-key-1'),但是nestedObject可能不可能具有多次相同的密钥。

我想这样做的原因(希望很明显)是为了加快正在运行的查询。具体来说,有问题的查询是:

SELECT tableOne.data AS dataOne, tableTwo.data AS dataTwo FROM tableOne
    JOIN tableTwo ON tableTwo.data->>'someField' = tableOne.id
    WHERE tableOne.data->'nestedObject'->'dynamic-key-goes-here' IS NOT NULL
        AND (tableOne.data->'nestedObject'->>'dynamic-key-goes-here')::integer > 0
    ORDER BY (tableOne.data->'nestedObject'->>'dynamic-key-goes-here')::integer DESC 
LIMIT 100;

以第二个查询为例,我可以对其进行EXPLAIN ANALYZE。我看到它最终对((((data -> 'nestedObject'::text) ->> 'dynamic-key-goes-here'::text))::integer > 0)的{​​{1}}进行了顺序扫描(不是并行seq扫描),这花费了大约75%的预期查询时间。

我知道,如果将其“正常”存储,那就太简单了。作为典型的关系数据(并且该数据是关系数据),但是不幸的是1.我从其他人那里继承了此代码,并且2.我目前无法进行数据库迁移,因此无法执行此操作。

因此,鉴于此,是否可以有效地在此数据上创建整数索引?

1 个答案:

答案 0 :(得分:2)

如果您要查找的键仅存在(相对)少量的值,则可以使用labels <- data.frame(variable = letters[1:3], label = c("Apple", "Banana", "Cherry"), stringsAsFactors = F) ggplot(df, aes(x = "x", y = value)) + geom_col() + facet_grid( ~ variable, labeller = as_labeller(with(labels, setNames(label, variable)))) (“ exists”运算符)将其过滤掉。该​​运算符可以使用JSONB值的索引。

例如:

?

并使用以下条件:

create index on the_table using gin (data  -> 'nestedObject);

但是,如果大多数“ nestedObjects”中都存在该密钥,这将无济于事。


如果您要查找一个特定值(例如dynamic-key = 123),则可以使用GIN索引和where data->'nestedObject' ? 'dynamic-key-1' -- this could use the index if feasible and (data->'nestedObject'->> 'dynamic-key-1')::integer > 100 运算符(例如@>,但是当您使用where data @> '{"nestedObject" : {"dynamic-key-1": 123}}'比较值时,确实很难建立索引。