我想使用 jsonb 列上的 GIN 索引进行模式匹配来提高查询性能
例如,我将表定义为:
CREATE TABLE my_table (
uuid text,
doc jsonb
);
在表文档的每一行中都有路径{A,B}。 B 是一个对象,可能是空的。路径中多了一个可选元素:可以不存在,也可以是C、D等
我可以为模式匹配创建一个将在下面列出的所有情况下使用的索引吗?
SELECT doc#>>'{A,B}'
FROM my_table
WHERE doc#>>'{A,B}' ILIKE '%example%';
SELECT doc#>>'{A,B,C}'
FROM my_table
WHERE doc#>>'{A,B,C}' ILIKE '%example%';
SELECT doc#>>'{A,B,D}'
FROM my_table
WHERE doc#>>'{A,B,D}' ILIKE '%example%';
我尝试将索引创建为:
CREATE INDEX my_index
ON my_table
USING GIN ((doc#>>'{A,B}') gin_trgm_ops)
不幸的是,它仅适用于路径为 {A,B} 的查询,而不适用于 {A,B,C}
一个索引可能适用于所有情况,但对于与索引表达式不完全匹配的索引,您必须以一种不自然的方式编写查询:
SELECT doc#>>'{A,B,C}'
FROM my_table
WHERE doc#>>'{A,B}' ILIKE '%example%' AND doc#>>'{A,B,C}' ILIKE '%example%';
doc#>>'{A,B,C}' ILIKE '%example%'
通常意味着doc#>>'{A,B}' ILIKE '%example%'
,但这不是 PostgreSQL 会为你推理出来的。这也并非在所有情况下都完全正确,如果一个的最终结果是字符串化的 JSON 对象,而另一个只是普通字符串,则需要在 JSON 中转义的字符将在 doc#>>'{A,B}'
中转义,但不会在 doc#>>'{A,B,C}'
中转义。
select '{"0":{"a":"b\"c"}}'::jsonb #>> '{0}';
---------------
{"a": "b\"c"}
select '{"0":{"a":"b\"c"}}'::jsonb #>> '{0,a}';
----------
b"c