0

我已经发布了一个类似的问题,但我必须精确一点......

这是原始帖子:[ 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。

您对如何提高性能有任何想法...?

4

0 回答 0