PostgreSQL未在JSONB上对GIN索引使用索引扫描

js5cn81o  于 2022-12-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(164)

我在PostgreSQL中有一个包含一个JSONB列的表。JSON看起来像这样-{'key':some_key, 'value': some_value}
我在JSON中使用-

CREATE INDEX t3_index ON t3 USING GIN ((data->'key'));

table的表面看起来像-

Table "public.t3"
 Column | Type  | Collation | Nullable | Default 
--------+-------+-----------+----------+---------
 data   | jsonb |           |          | 
Indexes:
    "t3_index" gin ((data -> 'key'::text))

当我使用key查询时,PostgreSQL正在进行序列扫描。

psql_eth=> explain (analyze, buffers) select * from t3 where data->>'key'='ZGJVcGdyYWRlXzIwMTcwNzE0ZGVkdXBsaWNhdGVEYXRh';
                                             QUERY PLAN                                             
----------------------------------------------------------------------------------------------------
 Seq Scan on t3  (cost=0.00..4201.65 rows=377 width=289) (actual time=0.017..42.976 rows=1 loops=1)
   Filter: ((data ->> 'key'::text) = 'ZGJVcGdyYWRlXzIwMTcwNzE0ZGVkdXBsaWNhdGVEYXRh'::text)
   Rows Removed by Filter: 75049
   Buffers: shared hit=3142
 Planning time: 0.068 ms
 Execution time: 42.996 ms
(6 rows)

1.为什么PostgreSQL要进行seq扫描?
1.如何使查询结果更快?如何使其使用GIN索引?

nx7onnlm

nx7onnlm1#

来自文档:
jsonb的默认GIN运算符类支持使用顶级键存在运算符?、?&和?的查询|运算符和路径/值存在运算符@〉。
该索引不适用于相等运算符(=)。可以改用简单的btree索引:

create index on t3 ((data->>'key'));
o0lyfsai

o0lyfsai2#

迟到了,但如果它仍然有帮助,见下文。
您已经使用了CREATE INDEX t3_index ON t3 USING GIN ((data->'key'));
就像documentation说的-
对于类型jsonb,jsonb_ops是默认值。
由于您没有提供任何运算符类,因此将为您选择默认值。
对于jsonb_ops运算符类,仅支持以下运算符-
??&?|@〉@?@@
=不在上述列表中,因此不受支持,即无法使用索引。
您可以改为将where子句更改为使用@>,然后重试-

explain (analyze, buffers) select * from t3 where data @> "{'key':'ZGJVcGdyYWRlXzIwMTcwNzE0ZGVkdXBsaWNhdGVEYXRh'}" ; 
// i have not tried the syntax or quotes usage - but something using @> will definitely work.

对于小表- planner可能仍然会选择Seq Scan,因为它可能会更快。但是既然你说你的表有712313行,@>方法肯定会使用GIN索引。

相关问题