PostgreSQL 10.4-如何为sql函数而不是运算符索引jsonb?

PostgreSQL 10.4-如何为sql函数而不是运算符索引jsonb?,postgresql,indexing,jsonb,Postgresql,Indexing,Jsonb,我有一个名为“k3_order”的表,其中有jsonb列“json_delivery” 该列的内容示例如下: { “交付成本”:“11.99”, “包成员”:[ “0000000 596034Q” ] } 我已经在json_交付上创建了索引->“packageNumbers”: CREATE INDEX test_idx ON k3_order USING gin(json_delivery->'packageNumbers'); 现在我使用这两个SQL查询: SELECT id, d

我有一个名为“k3_order”的表,其中有jsonb列“json_delivery”

该列的内容示例如下:

{
“交付成本”:“11.99”,
“包成员”:[
“0000000 596034Q”
]
}
我已经在json_交付上创建了索引->“packageNumbers”:

CREATE INDEX test_idx ON k3_order USING gin(json_delivery->'packageNumbers');
现在我使用这两个SQL查询:

SELECT id, delivery_method_id 
FROM k3_order 
WHERE jsonb_exists (json_delivery->'packageNumbers', '0000000596034Q');

SELECT id, delivery_method_id 
FROM k3_order 
WHERE json_delivery->'packageNumbers' ? '0000000596034Q';
第二个更快,并且使用索引,但第一个没有

有没有办法在PostgreSQL 10.4中创建索引,以便查询1)使用它

这在PostgreSQL 10.4或更新版本中是否可能实现

解释分析选择id、交付方法\u id
从k3_订单
存在jsonb_的地方(json_交付->'packageNumbers',>'0000000 596034q');
产生:

Seq Scan on k3_order  (cost=0.00..117058.10 rows=216847 width=8 (actual time=162.001..569.863 rows=1 loops=1)
Filter: jsonb_exists((json_delivery -> 'packageNumbers'::text), '0000000596034Q'::text)
Rows Removed by Filter: 650539

Planning time: 0.748 ms
Execution time: 569.886 ms
Bitmap Heap Scan on k3_order  (cost=21.04..2479.03 rows=651 width=8) (actual time=0.022..0.022 rows=1 loops=1)
Recheck Cond: ((json_delivery -> 'packageNumbers'::text) ? '0000000596034Q'::text)
Heap Blocks: exact=1
  ->  Bitmap Index Scan on test_idx  (cost=0.00..20.88 rows=651 width=0) (actual time=0.016..0.016 rows=1 loops=1)
        Index Cond: ((json_delivery -> 'packageNumbers'::text) ? '0000000596034Q'::text)

Planning time: 0.182 ms
Execution time: 0.050 ms
解释分析选择id、交付方法\u id
从k3_订单
其中json_交付->“packageNumbers”?'0000000 596034q';
产生:

Seq Scan on k3_order  (cost=0.00..117058.10 rows=216847 width=8 (actual time=162.001..569.863 rows=1 loops=1)
Filter: jsonb_exists((json_delivery -> 'packageNumbers'::text), '0000000596034Q'::text)
Rows Removed by Filter: 650539

Planning time: 0.748 ms
Execution time: 569.886 ms
Bitmap Heap Scan on k3_order  (cost=21.04..2479.03 rows=651 width=8) (actual time=0.022..0.022 rows=1 loops=1)
Recheck Cond: ((json_delivery -> 'packageNumbers'::text) ? '0000000596034Q'::text)
Heap Blocks: exact=1
  ->  Bitmap Index Scan on test_idx  (cost=0.00..20.88 rows=651 width=0) (actual time=0.016..0.016 rows=1 loops=1)
        Index Cond: ((json_delivery -> 'packageNumbers'::text) ? '0000000596034Q'::text)

Planning time: 0.182 ms
Execution time: 0.050 ms

索引只能在以下情况下由查询使用:

  • WHERE
    条件包含形式为
    的表达式,其中

    • 已在

    • 是索引的运算符类的索引族中的运算符

    • 是在索引扫描期间保持不变的表达式

  • ORDER BY
    子句的顺序与索引定义的顺序相同或完全相反,索引访问方法支持排序(从v13开始,如果索引包含
    ORDER BY
    子句的起始列,也可以使用索引)

  • PostgreSQL版本为v12及更高版本,其中的
    条件包含一个
    bool_func(…)
    形式的表达式,其中函数返回
    布尔值并具有

现在
json\u交付->“packageNumbers”?'0000000 596034Q'
满足第一个条件,因此可以使用索引扫描

jsonb_exists(json_delivery->'packageNumbers',>'0000000 596034q')
仅当存在针对
jsonb_exists的planner支持函数时才能使用索引,但没有:

SELECT prosupport FROM pg_proc
WHERE proname = 'jsonb_exists';

 prosupport 
════════════
 -
(1 row)

我刚刚检查过,并且
jsonb_exists
没有支持函数。那么jsonb_exists返回布尔值,应该是这样的。下面是所有PostgreSQL json相关函数的列表:是的,但请参阅我的最后一个查询,它显示它没有支持函数。所以它不会起作用。我们可能会欢迎一个补丁来添加一个支持函数。如果这种查询使用索引:
SELECT id,delivery\u method\u id FROM k3\u order,其中jsonb\u存在(CAST(jsonb\u object\u field\u text(json\u delivery,'packageNumbers')作为jsonb,'0000000 596034q')
如我所说,欢迎您编写修补程序。我刚刚在另一台测试机器上安装了PostgreSQL 13,并从pg_proc中选择了prosupport,proname='jsonb_exists'显示它受支持,但另一个查询仍然不使用索引。