Postgres 9,6 - JSONB? у оператора отсутствует индекс, но присутствует с? оператор - PullRequest
0 голосов
/ 13 марта 2020

Я делаю несколько запросов в postgres 9,6, включая столбец jsonb, столбец int, два индекса (по одному для каждого столбца) и оператор ?|. Часть jsonb запроса использует свой индекс просто отлично, а столбец int - нет.

Странная вещь в том, что оба индекса работают должным образом при разбиении условия ?| на несколько or ? условий.

Вот особенности того, с чем я работаю.

  • int index

    • CREATE INDEX team_id_index ON revisions (team_id);
  • jsonb index

    • CREATE INDEX _group_ids_gin_index ON revisions USING GIN(_group_ids jsonb_ops);

полуработающий ?| запрос

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

Это не имеет большого значения, если мне просто нужно переписать все мои запросы, используя ? вместо ?|, но загадка ПОЧЕМУ это делает меня сводит меня с ума. Пожалуйста, помогите для моего здравомыслия!

1 Ответ

2 голосов
/ 13 марта 2020

Планы разные, потому что оценки разные. Избирательность ?| оценивается без учета длины списка в RHS, в то время как планирование Or неявно учитывает это.

Сканирование индекса растрового изображения на _group_ids_gin_index ... rows = 587

BitmapOr ... rows = 1173

Чем меньше, по вашему мнению, будет растровое изображение, тем меньше смысла будет пытаться сделать его даже меньше при сканировании отдельного индекса для добавления в BitmapAnd.

Планирование в этой области не улучшилось с 9.6, и у вас не так много хороших вариантов, кроме переписывания запросов, как вы уже указали.

Обратите внимание, что оценки в любом случае слишком далеки, просто один из способов быть случайно приведёт к созданию лучших планов. Если бы вы использовали собственные массивы, а не инкапсулировали их в JSONB, это, вероятно, имело бы лучшие оценки, поэтому, вероятно, могло бы придумывать лучшие планы более надежно, чем в случае аварии.

...