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

Postgresql Postgres JSONB-子对象的所有动态(整数)属性的索引,postgresql,jsonb,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 m

我的数据库中有一个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
s可能具有相同的键(例如,许多对象可能具有
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)
tableOne
,这占用了大约75%的预期查询时间

我知道,如果它是“正常”存储的,这将是微不足道的,例如,作为典型的关系数据(并且该数据是关系数据),但不幸的是1。我从其他人那里继承了这段代码。我现在不能进行数据库迁移,所以我不能这样做


因此,有可能有效地将此数据创建为整数的索引吗?

如果您要查找的键只存在于(相对)少量的值中,那么可以使用
(“exists”)运算符过滤掉这些值。该运算符可以对JSONB值使用索引

e、 g:

并使用如下条件:

where data->'nestedObject' ? 'dynamic-key-1' -- this could use the index if feasible
  and (data->'nestedObject'->> 'dynamic-key-1')::integer > 100
但是,如果该键存在于大多数“嵌套对象”中,则这并没有真正的帮助



如果您正在查找一个特定值(例如dynamic key=123),则可以使用GIN索引和
>
运算符(例如
where data@>{“nestedObject”):{“dynamic-key-1”:123}来支持此操作“
但是当您使用
比较值时,这确实很难索引。

不相关,但是:
不是空的测试是不必要的,因为如果结果是
空的,那么
>0
也将是假的(但删除该复选框不会改变性能方面的任何变化——本质上只是化妆品)“如果您要查找的密钥只存在于(相对)少量值中”是的!正在查找的密钥只存在于
where data->'nestedObject' ? 'dynamic-key-1' -- this could use the index if feasible
  and (data->'nestedObject'->> 'dynamic-key-1')::integer > 100