PostgreSQL 10.4 - 如何为 sql 函数而非运算符索引 jsonb?
PostgreSQL 10.4 - how to index jsonb for sql functions not operators?
我有一个名为“k3_order”的 table,jsonb 列为“json_delivery”。
该列的示例内容是:
{
"delivery_cost": "11.99",
"packageNumbers": [
"0000000596034Q"
]
}
我在 json_delivery->'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 或更高版本中是否可行?
EXPLAIN ANALYZE SELECT id, delivery_method_id
FROM k3_order
WHERE jsonb_exists (json_delivery->'packageNumbers', > '0000000596034Q');
产生:
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
EXPLAIN ANALYZE SELECT id, delivery_method_id
FROM k3_order
WHERE json_delivery->'packageNumbers' ? '0000000596034Q';
产生:
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
条件包含 <em><索引表达式></em> <em><运算符> 形式的表达式</em> <em><常量></em>
,其中
已在 <em><索引表达式></em>
上创建索引
<em><operator></em>
是运算符 class 的索引族中的一个运算符指数
<em><constant></em>
是在索引扫描期间保持不变的表达式
ORDER BY
子句与索引定义的顺序相同或完全相反,索引访问方式支持排序(从v13开始,也可以使用索引,如果包含 ORDER BY
子句的起始列)
PostgreSQL版本为v12以上,WHERE
条件包含bool_func(...)
形式的表达式,其中函数returnsboolean
并且有一个 planner support function.
现在json_delivery->'packageNumbers' ? '0000000596034Q'
满足第一个条件,可以使用索引扫描
jsonb_exists(json_delivery->'packageNumbers', > '0000000596034Q')
只有在 jsonb_exists
有规划器支持功能的情况下才能使用索引,但是 none:
SELECT prosupport FROM pg_proc
WHERE proname = 'jsonb_exists';
prosupport
════════════
-
(1 row)
我有一个名为“k3_order”的 table,jsonb 列为“json_delivery”。
该列的示例内容是:
{
"delivery_cost": "11.99",
"packageNumbers": [
"0000000596034Q"
]
}
我在 json_delivery->'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 或更高版本中是否可行?
EXPLAIN ANALYZE SELECT id, delivery_method_id
FROM k3_order
WHERE jsonb_exists (json_delivery->'packageNumbers', > '0000000596034Q');
产生:
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
EXPLAIN ANALYZE SELECT id, delivery_method_id
FROM k3_order
WHERE json_delivery->'packageNumbers' ? '0000000596034Q';
产生:
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
条件包含<em><索引表达式></em> <em><运算符> 形式的表达式</em> <em><常量></em>
,其中已在
上创建索引<em><索引表达式></em>
<em><operator></em>
是运算符 class 的索引族中的一个运算符指数<em><constant></em>
是在索引扫描期间保持不变的表达式
ORDER BY
子句与索引定义的顺序相同或完全相反,索引访问方式支持排序(从v13开始,也可以使用索引,如果包含ORDER BY
子句的起始列)PostgreSQL版本为v12以上,
WHERE
条件包含bool_func(...)
形式的表达式,其中函数returnsboolean
并且有一个 planner support function.
现在json_delivery->'packageNumbers' ? '0000000596034Q'
满足第一个条件,可以使用索引扫描
jsonb_exists(json_delivery->'packageNumbers', > '0000000596034Q')
只有在 jsonb_exists
有规划器支持功能的情况下才能使用索引,但是 none:
SELECT prosupport FROM pg_proc
WHERE proname = 'jsonb_exists';
prosupport
════════════
-
(1 row)