我已经发布了一个类似的问题,但我必须精确一点......
这是原始帖子:[ Postgres jsonb search in array with greater operator (with jsonb_array_elements)
如果我总结一下,
这是数据库声明(简化):
CREATE TABLE documents (
document_id int4 NOT NULL GENERATED BY DEFAULT AS IDENTITY,
data_block jsonb NULL,
type varchar(10)
);
这是插入的一个例子。
INSERT INTO documents (document_id, data_block)
VALUES(878979,
{"COMMONS": {"DATE": {"value": "2017-03-11"}},
"CARS": [
{"MODEL": {"value": "FERRARI F40"}},
{"MODEL": {"value": "PORSCHE CAYENNE"}},
{"MODEL": {"value": "FERRARI Testarossa"}}
]}, 'garage');
INSERT INTO documents (document_id, data_block)
VALUES(977656,
{"INVOICE": {"TOTAL_AMOUNT": {"value": "100.00"}},
"PAYABLE_INVOICE_LINES": [
{"AMOUNT": {"value": 75.00}},
{"AMOUNT": {"value": 25.00}}
]}, 'invoices');
INSERT INTO documents (document_id, data_block)
VALUES(345,
{"INVOICE": {"TOTAL_AMOUNT": {"value": "200.00"}},
"PAYABLE_INVOICE_LINES": [
{"AMOUNT": {"value": 125.00}},
{"AMOUNT": {"value": 75.00}}
]}, 'invoices');
事实上,我可以在 JSONB 列中存储任何内容,现在我想使用特定的运算符进行搜索。
查询示例:
PAYABLE_INVOICE_LINES 中至少有一行大于 100.00 的所有文档:data_block.PAYABLE_INVOICE_LINES.AMOUNT > 100.00
所有在 CARS 中以 'FERRARI' 开头的行的文档:data_block.CARS.MODEL like 'FERRARI%'
TOTAL_AMOUNT = 100.00 的所有文档
COMMONS.DATE > "2018-04-30" 的所有文件
列表中包含 CARS.MODEL 的所有文件('PORSCHE CAYENNE')
data_block.PAYABLE_INVOICE_LINES.AMOUNT 介于 100.00 和 150.00 之间的所有文档
Bref,我想查询所有我想要的。我想通过排序限制为 50 个结果。
我的数据库包含数百万行,我有一些性能问题......
我已经使用 EXISTS 实现了解决方案:
select *
from documents d
where exists (
select 1
from jsonb_array_elements(d.data_block -> 'PAYABLE_INVOICE_LINES') as pil
where (pil->'AMOUNT'->>'value')::decimal >= 1000)
limit 50;
这很好但还不够……有些查询很慢。> 20 秒。
我不知道文件的结构。我们可以插入汽车、发票、身份证,客户可以创建自己的结构。因此,我无法轻松创建索引,也无法创建函数来准备结果。
在 JSON 对象中的数组上进行搜索时,查询非常慢。像 PAYABLE_INVOICE_LINES。
您对如何提高性能有任何想法...?