索引扫描不适用于 postgres 中的 json 数据集

Posted

技术标签:

【中文标题】索引扫描不适用于 postgres 中的 json 数据集【英文标题】:Index scan is not working on json data set in postgres 【发布时间】:2020-04-06 18:33:40 【问题描述】:

我正在尝试了解如何使用某些过滤条件从PostgreSQL 中的JSON 文件中提取数据。

这是我的查询,

创建如下索引,

CREATE INDEX idx_startTimeL_n
    ON mytable USING btree
    (((data -> 'info'::text) ->> 'startTimeL'::text) ) 

如果我运行解释选择查询

EXPLAIN   SELECT * FROM mytable
      WHERE (((data -> 'info'::text) ->> 'startTimeL'::text)::double precision) <= (date_part('epoch'::text, now()) * 1000::double precision)
      AND ((data -> 'info'::text) ->> 'startTimeL'::text)::double precision) >= (date_part('epoch'::text, now()) * 1000::double precision - 3600000::double precision)
     LIMIT 400000;

查询规划器的结果是,

"Limit  (cost=0.00..36371.90 rows=220700 width=1568)"
"  ->  Seq Scan on mytable  (cost=0.00..36371.90 rows=220700 width=1568)"
"        Filter: (((((data -> 'info'::text) ->> 'startTimeL'::text))::double precision <= (date_part('epoch'::text, now()) * '1000'::double precision)) AND ((((data -> 'info'::text) ->> 'startTimeL'::text))::double precision >= ((date_part('epoch'::text, now()) * '1000'::double precision) - '3600000'::double precision)))"

所以,我的问题是为什么发生seq scan 而不是index scan,即使表使用过滤条件索引?

【问题讨论】:

因为你的索引表达式与 WHERE 子句中使用的表达式不同 是否可以在 where 中创建具有相同给定表达式的索引? 【参考方案1】:

您的示例查询有语法错误,括号不平衡。

如果要查找具有双精度的索引,那么这就是必须定义索引的方式。

CREATE INDEX ON mytable USING btree
    (((data -> 'info' ->> 'startTimeL')::double precision))

【讨论】:

以上是关于索引扫描不适用于 postgres 中的 json 数据集的主要内容,如果未能解决你的问题,请参考以下文章

Postgres:强制分析器使用位图扫描而不是索引扫描

防止在 Postgres 中为特定查询使用索引

索引扫描时 Postgres 不使用索引是更好的选择

Postgres 仅索引扫描耗时太长

ElasticSearch 索引适用于 REST API,但不适用于 C# 代码

为啥 Postgres 在使用覆盖索引时仍然进行位图堆扫描?