PostgreSQL 未对 JSONB 上的 GIN 索引使用索引扫描
Posted
技术标签:
【中文标题】PostgreSQL 未对 JSONB 上的 GIN 索引使用索引扫描【英文标题】:PostgreSQL not using index scan over GIN index on JSONB 【发布时间】:2018-01-25 11:47:00 【问题描述】:我在 PostgreSQL 中有一张表,其中包含一个 JSONB 列。 JSON 看起来像这样-'key':some_key, 'value': some_value
.
我使用 -
key
CREATE INDEX t3_index ON t3 USING GIN ((data->'key'));
表格的schama看起来像-
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)
-
PostgreSQL 为什么要进行 seq 扫描?
如何让查询结果更快?如何让它使用 GIN 索引?
【问题讨论】:
请edit您的问题并添加使用explain (analyze, buffers)
(不仅仅是explain
)生成的执行计划
优化器假设表只有 334 行,所以 seq 扫描是自然的选择。您的统计数据似乎不是最新的。运行analyze t4
后计划会改变吗?
不,唯一可见的区别是 rows=351 (同时更改的总行数只有几 1000 秒)。 select count(*) from t4
给出 712313
为什么/如何假设 334 行?
Execution time: 42.996 ms
您想要更快吗?顺便说一句,你的桌子叫什么名字? t3 t4.
【参考方案1】:
来自the documentation:
jsonb 的默认 GIN 运算符类支持使用***键存在运算符 ?、?& 和 ?| 的查询运算符和路径/值存在运算符@>.
索引不适用于等式运算符 (=)。您可以改用简单的 btree 索引:
create index on t3 ((data->>'key'));
【讨论】:
以上是关于PostgreSQL 未对 JSONB 上的 GIN 索引使用索引扫描的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL 中 JSONB[] (JSONB ARRAY) 数据类型有啥用?