【问题标题】:Postgres is not making use of the available indexPostgres 没有使用可用的索引
【发布时间】:2021-12-29 08:19:19
【问题描述】:

我有一张如下表:

create table Configuration(
      config_id varchar,
      configurations jsonb
)

示例配置列如下所示:

{
   "orderProcessing":{
      "limit":3000,
      "config1":false,
      "config2":true,
      "config3": "Example Text"

   }
}

注意:“orderProcessing”和“limit”不是配置的必填字段,在某些行中会丢失。

我创建了一个这样的 Btree 索引:

create index id_limit_idx on configuration(config_id, (configurations->'orderProcessing'->>'limit'));

我需要像这样基于 orderProcessing.limit 进行聚合:

select  configurations->'orderProcessing'->>'limit', count(*)
from configuration
where config_id = 'some_id'
GROUP BY (configurations->'orderProcessing'->>'limit')

但是查询没有使用 id_limit_idx 索引,而是进行了顺序扫描。

-------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize GroupAggregate  (cost=143843.65..143857.83 rows=22 width=40) (actual time=100.556..102.656 rows=6 loops=1)
   Group Key: (((configurations -> 'orderProcessing'::text) ->> 'limit'::text))
   ->  Gather Merge  (cost=143843.65..143856.95 rows=110 width=40) (actual time=100.545..102.639 rows=27 loops=1)
         Workers Planned: 5
         Workers Launched: 5
         ->  Sort  (cost=142843.57..142843.62 rows=22 width=40) (actual time=96.222..96.224 rows=4 loops=6)
               Sort Key: (((configurations -> 'orderProcessing'::text) ->> 'limit'::text))
               Sort Method: quicksort  Memory: 25kB
               Worker 0:  Sort Method: quicksort  Memory: 25kB
               Worker 1:  Sort Method: quicksort  Memory: 25kB
               Worker 2:  Sort Method: quicksort  Memory: 25kB
               Worker 3:  Sort Method: quicksort  Memory: 25kB
               Worker 4:  Sort Method: quicksort  Memory: 25kB
               ->  Partial HashAggregate  (cost=142842.75..142843.08 rows=22 width=40) (actual time=96.185..96.187 rows=4 loops=6)
                     Group Key: ((configurations -> 'orderProcessing'::text) ->> 'limit'::text)
                     ->  Parallel Seq Scan on configuration  (cost=0.00..142544.62 rows=59626 width=32) (actual time=5.988..86.741 rows=48976 loops=6)
                           Filter: (config_id = 'some_id'::text)
                           Rows Removed by Filter: 279276
 Planning Time: 0.103 ms
 Execution Time: 102.699 ms
(20 rows)                                                                            

这让我怀疑我创建的索引不正确。也许我所做的不是在 json 元素的嵌套字段上创建索引的正确方法。

非常感谢这里的任何帮助。

【问题讨论】:

  • "查询没有使用 id_limit_idx 索引" - 它显然可以在步骤Bitmap Index Scan on id_limit_idx 中看到 - 我没有看到任何 Seq Scan计划。
  • @a_horse_with_no_name 我提供的查询计划是在我通过设置SET enable_seqscan = OFF 强制它使用索引之后。这就是没有 Seq 扫描的原因。但正如您所见,它仍在运行Parallel Bitmap Heap Scan。所以,问题是为什么需要这一步,因为所需的信息已经是索引的一部分
  • 显示使用 Seq Scan 的人会更好地理解为什么会发生这种情况。
  • @a_horse_with_no_name 我无法将其粘贴到评论中。因此,更新了原始问题中的查询计划。请看一看。
  • @user14870583 好。切勿为请求的信息创建评论。 总是更新实际问题。然后,如果您认为有必要通知请求者,您可以发表评论表明已完成。

标签: sql postgresql indexing query-optimization


【解决方案1】:

PostgreSQL 无法像您创建的那样对表达式索引执行仅索引扫描。这不是原则问题,只是还没有实施。

仅索引扫描只能使用(config_id, configurations) 上的索引,但出于可以理解的原因,这不是一个选项。

最佳解决方案是将configurations->'orderProcessing'->>'limit' 建模为普通表列而不是JSON 属性。

【讨论】:

  • 感谢您的回复。但我的想法是提供所需信息(在本例中为 config_id 和限制)作为同一索引的一部分。因此,该 postgress 可以只使用索引而无需进行表查找(顺序或堆扫描)。为了进行实验,我添加了新列并填充了它 ``` update configuration set limit = (configurations->'orderProcessing'->>'limit')::int ``` 并在 ``` create index id_limit on configuration(config_id, limit) ``` 然后我的查询按预期使用索引。这就是为什么我怀疑原始索引不正确
猜你喜欢
  • 2023-03-06
  • 2020-01-24
  • 2015-06-29
  • 1970-01-01
  • 2014-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多