Postgres JSONB - 子对象的所有动态(整数)属性的索引
Postgres JSONB - index on all dynamic (integer) attributes of subobject
我的数据库中有一个 JSONB table,如下所示:
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'
),但 不可能 [=14] =] 多次使用相同的密钥。
我想这样做的原因是(希望很明显)加快查询 运行。具体来说,有问题的查询是:
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
。我看到它最终在 tableOne
上对 ((((data -> 'nestedObject'::text) ->> 'dynamic-key-goes-here'::text))::integer > 0)
进行顺序扫描( 而不是 并行序列扫描),这需要大约 75% 的预期查询时间.
我知道如果它被存储起来这将是微不足道的 "normally," 即。作为典型的关系数据(并且这个数据是关系数据),但不幸的是 1. 我从别人那里继承了这段代码,以及 2. 我现在无法进行数据库迁移,所以我不能这样做。
鉴于此,是否可以有效地为该数据创建整数索引?
如果您要查找的键仅出现在(相对)少量的值中,则可以使用 ?
(“存在”)运算符将其过滤掉。该运算符可以在 JSONB 值上使用索引。
例如:
create index on the_table using gin (data -> 'nestedObject');
并使用如下条件:
where data->'nestedObject' ? 'dynamic-key-1' -- this could use the index if feasible
and (data->'nestedObject'->> 'dynamic-key-1')::integer > 100
但是,如果大多数“nestedObjects”中都存在该键,这将无济于事。
如果您正在寻找一个特定值(例如 dynamic-key = 123),可以使用 GIN 索引和 @>
运算符来支持,例如where data @> '{"nestedObject" : {"dynamic-key-1": 123}}'
但是当您使用 >
比较值时,这真的很难索引。
我的数据库中有一个 JSONB table,如下所示:
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'
),但 不可能 [=14] =] 多次使用相同的密钥。
我想这样做的原因是(希望很明显)加快查询 运行。具体来说,有问题的查询是:
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
。我看到它最终在 tableOne
上对 ((((data -> 'nestedObject'::text) ->> 'dynamic-key-goes-here'::text))::integer > 0)
进行顺序扫描( 而不是 并行序列扫描),这需要大约 75% 的预期查询时间.
我知道如果它被存储起来这将是微不足道的 "normally," 即。作为典型的关系数据(并且这个数据是关系数据),但不幸的是 1. 我从别人那里继承了这段代码,以及 2. 我现在无法进行数据库迁移,所以我不能这样做。
鉴于此,是否可以有效地为该数据创建整数索引?
如果您要查找的键仅出现在(相对)少量的值中,则可以使用 ?
(“存在”)运算符将其过滤掉。该运算符可以在 JSONB 值上使用索引。
例如:
create index on the_table using gin (data -> 'nestedObject');
并使用如下条件:
where data->'nestedObject' ? 'dynamic-key-1' -- this could use the index if feasible
and (data->'nestedObject'->> 'dynamic-key-1')::integer > 100
但是,如果大多数“nestedObjects”中都存在该键,这将无济于事。
如果您正在寻找一个特定值(例如 dynamic-key = 123),可以使用 GIN 索引和 @>
运算符来支持,例如where data @> '{"nestedObject" : {"dynamic-key-1": 123}}'
但是当您使用 >
比较值时,这真的很难索引。