Postgres 9.6 - jsonb ?|运算符缺少索引,但存在 ?操作员

Postgres 9.6 - jsonb ?| operator missing index, but present with ? operator

我正在 postgres 9,6 中进行一些查询,涉及一个 jsonb 列、一个 int 列、两个索引(每个列一个)和 ?| 运算符。查询的 jsonb 部分很好地使用了它的索引,但 int 列不是。

奇怪的是,当将 ?| 条件拆分为多个 or ? 条件时,两个索引都按预期工作。

以下是我正在处理的细节。

半途而废?|查询

select * 
from revisions 
where team_id = 1 
and _group_ids ?| '{"0","91"}';
Bitmap Heap Scan on revisions  (cost=224.42..2214.66 rows=92 width=992) (actual time=7.783..40.178 rows=4454 loops=1)
  Recheck Cond: (_group_ids ?| '{0,91}'::text[])
  Filter: (team_id = 1)
  Rows Removed by Filter: 63027
  Heap Blocks: exact=5129
  ->  Bitmap Index Scan on _group_ids_gin_index  (cost=0.00..224.40 rows=587 width=0) (actual time=7.086..7.086 rows=67481 loops=1)
        Index Cond: (_group_ids ?| '{0,91}'::text[])
Planning time: 0.142 ms
Execution time: 40.401 ms

完全工作?查询

select * 
from revisions 
where team_id = 1 
and (_group_ids ? '0' or _group_ids ? '91');
Bitmap Heap Scan on revisions  (cost=2414.55..3091.44 rows=184 width=992) (actual time=12.965..16.162 rows=4454 loops=1)
  Recheck Cond: (((_group_ids ? '0'::text) OR (_group_ids ? '91'::text)) AND (team_id = 1))
  Heap Blocks: exact=818
  ->  BitmapAnd  (cost=2414.55..2414.55 rows=184 width=0) (actual time=12.844..12.844 rows=0 loops=1)
        ->  BitmapOr  (cost=424.89..424.89 rows=1173 width=0) (actual time=7.329..7.329 rows=0 loops=1)
              ->  Bitmap Index Scan on _group_ids_gin_index  (cost=0.00..212.40 rows=587 width=0) (actual time=6.439..6.439 rows=67076 loops=1)
                    Index Cond: (_group_ids ? '0'::text)
              ->  Bitmap Index Scan on _group_ids_gin_index  (cost=0.00..212.40 rows=587 width=0) (actual time=0.887..0.887 rows=405 loops=1)
                    Index Cond: (_group_ids ? '91'::text)
        ->  Bitmap Index Scan on team_id_index  (cost=0.00..1989.36 rows=91858 width=0) (actual time=5.218..5.218 rows=90229 loops=1)
              Index Cond: (team_id = 1)
Planning time: 0.154 ms
Execution time: 16.540 ms

如果我只需要使用 ? 而不是 ?| 重写我的所有查询,这没什么大不了的,但是 WHY 的神秘之处正在发生这真让我抓狂。请帮助我理智!

计划不同是因为估计不同。 ?| 的选择性是在不查看 RHS 上的列表长度的情况下估算的,而 Or 规划确实隐含地考虑了这一点。

Bitmap Index Scan on _group_ids_gin_index ... rows=587

BitmapOr ... rows=1173

您认为位图开始时越小,尝试通过扫描单独的索引以添加到 BitmapAnd 来使其更小的意义就越小。

自 9.6 以来,这方面的规划没有改进,除了您已经指出的重写查询之外,您没有太多好的选择。

请注意,在任何一种情况下,估计都会偏离,只是一种意外偏离的方式会导致更好的计划。如果您使用本机数组而不是将它们封装在 JSONB 中,它可能会有更好的估计,因此可能会比意外更可靠地提出更好的计划。