JSONB 字段对象 _array_ 上的 PostgreSQL 视图(带索引)
PostgreSQL View on a JSONB field object _array_ (with indexing)
问题
如何基于 JSONB 字段对象 array[ 创建 PostgreSQL View =42=],具有 适当的索引 ?示例如下。
- 从概念上讲,在与视图和 JSONB 数组一起使用时应如何应用索引?
- 创建相关索引的正确语法是什么?
- 示例视图是否给出了 correct/optimal 构建此用例视图的方法?
例子
Table
CREATE TABLE "ProductLists"
(
id uuid NOT NULL DEFAULT gen_random_uuid(),
listName text NOT NULL
productIds jsonb NOT NULL DEFAULT '[{ productId:0 }]'::jsonb,
)
视图(可以更改)
具有以下观点:
SELECT "ProductLists".id AS listId,
jsonb_array_elements("ProductLists".productIds) ->> 'productId'::text AS productId
FROM "ProductLists";
因素
- JSONB Root 是一个数组,而不是一个对象(在大多数索引示例中并非如此)
- 可能会有数百万个 ProductList 项目
- 每个列表中的productId数量通常会少于100个
- table 将具有高读取和写入
- 视图 SQL 示例可能是也可能不是最佳的目的,并且可以更改
感谢任何意见!
jsonb 列上的 GIN 索引将支持 several JSON operators。其中之一是 @>
运算符,它也适用于 JSON 数组。
以下索引:
create index on product_list using gin (product_ids);
可能会使用上述索引的查询如下所示:
select *
from product_list
where product_ids @> '[{"productId": 42}]'::jsonb;
您建议的视图无法使用索引,因为 JSONB 列不是视图的一部分,并且必须能够将 [= 上的条件下推37=] 列。
在视图中使用索引的唯一方法是在其中包含 JSON 列:
create view normalized_list
as
SELECT pl.id AS list_id,
t.product_id,
pl.product_ids
FROM product_list pl
CROSS JOIN jsonb_array_elements(pl.product_ids) ->> 'id' AS t(product_id)
;
这样的查询:
select id, product_Id
from normalized_list
where product_ids @> '[{"id":42}]'::jsonb;
将使用 GIN 索引。
请注意,如果您 仅 想以非规范化方式存储 ID,则原生整数数组 (product_ids int[]
) 会更高效并且会使 table 小得多
https://www.postgresql.org/docs/current/datatype-json.html
{
"tags": [
"enim",
"aliquip",
"qui"
]
}
-- Find documents in which the key "tags" contains key or array element "qui"
SELECT * FROM api WHERE jdoc -> 'tags' ? 'qui';
Still, with appropriate use of expression indexes, the above query can
use an index. If querying for particular items within the "tags" key
is common, defining an index like this may be worthwhile:
CREATE INDEX idxgintags ON api USING gin ((jdoc -> 'tags'));
Now, the WHERE
clause jdoc -> 'tags' ? 'qui'
will be recognized as an
application of the indexable operator ?
to the
indexed expression jdoc-> 'tags'
.
因此,如果您要从
更改结构
'[{ "productId":0 }, { "productId":0 }]'
至
'{"productIds": ["0", "1"]}'
甚至
'{"products": {"0": {"title": "aaa"}, "1": {"title": "bbb"}}}'
你可以建立合适的索引
问题
如何基于 JSONB 字段对象 array[ 创建 PostgreSQL View =42=],具有 适当的索引 ?示例如下。
- 从概念上讲,在与视图和 JSONB 数组一起使用时应如何应用索引?
- 创建相关索引的正确语法是什么?
- 示例视图是否给出了 correct/optimal 构建此用例视图的方法?
例子
Table
CREATE TABLE "ProductLists"
(
id uuid NOT NULL DEFAULT gen_random_uuid(),
listName text NOT NULL
productIds jsonb NOT NULL DEFAULT '[{ productId:0 }]'::jsonb,
)
视图(可以更改)
具有以下观点:
SELECT "ProductLists".id AS listId,
jsonb_array_elements("ProductLists".productIds) ->> 'productId'::text AS productId
FROM "ProductLists";
因素
- JSONB Root 是一个数组,而不是一个对象(在大多数索引示例中并非如此)
- 可能会有数百万个 ProductList 项目
- 每个列表中的productId数量通常会少于100个
- table 将具有高读取和写入
- 视图 SQL 示例可能是也可能不是最佳的目的,并且可以更改
感谢任何意见!
jsonb 列上的 GIN 索引将支持 several JSON operators。其中之一是 @>
运算符,它也适用于 JSON 数组。
以下索引:
create index on product_list using gin (product_ids);
可能会使用上述索引的查询如下所示:
select *
from product_list
where product_ids @> '[{"productId": 42}]'::jsonb;
您建议的视图无法使用索引,因为 JSONB 列不是视图的一部分,并且必须能够将 [= 上的条件下推37=] 列。
在视图中使用索引的唯一方法是在其中包含 JSON 列:
create view normalized_list
as
SELECT pl.id AS list_id,
t.product_id,
pl.product_ids
FROM product_list pl
CROSS JOIN jsonb_array_elements(pl.product_ids) ->> 'id' AS t(product_id)
;
这样的查询:
select id, product_Id
from normalized_list
where product_ids @> '[{"id":42}]'::jsonb;
将使用 GIN 索引。
请注意,如果您 仅 想以非规范化方式存储 ID,则原生整数数组 (product_ids int[]
) 会更高效并且会使 table 小得多
https://www.postgresql.org/docs/current/datatype-json.html
{ "tags": [ "enim", "aliquip", "qui" ] } -- Find documents in which the key "tags" contains key or array element "qui" SELECT * FROM api WHERE jdoc -> 'tags' ? 'qui';
Still, with appropriate use of expression indexes, the above query can use an index. If querying for particular items within the "tags" key is common, defining an index like this may be worthwhile:
CREATE INDEX idxgintags ON api USING gin ((jdoc -> 'tags'));
Now, the
WHERE
clausejdoc -> 'tags' ? 'qui'
will be recognized as an application of the indexable operator
?
to the indexed expressionjdoc-> 'tags'
.
因此,如果您要从
更改结构'[{ "productId":0 }, { "productId":0 }]'
至
'{"productIds": ["0", "1"]}'
甚至
'{"products": {"0": {"title": "aaa"}, "1": {"title": "bbb"}}}'
你可以建立合适的索引