Подтвердить что ты не робот

Как запрос массива postgres с использованием индекса gin?

У меня есть столбец массива postgres с индексом gin:

CREATE TABLE things (
    id integer NOT NULL,
    tags character varying(255)[]
);

CREATE INDEX index_things_on_tags ON things USING gin (tags);

Есть несколько способов проверить наличие элемента в столбце, используя различные операторы массива. Вот те, которые я видел:

  • select * from things where 'blue' = ANY (tags)
  • select * from things where tags <@ '{"blue"}'
  • select * from things where '{"blue","yellow"}' && tags;

В postgres 9.3:

  • Будет ли первый использовать индекс gin?
  • Я уверен, что второй будет использовать индекс. Однако он отличается от первого. это не позволяет мне проверить, является ли синим один из тегов, он требует указать точный массив. Есть ли способ сделать стиль синтаксиса в 2 достижением того, что 1 достигает?
  • В третьем я хочу любую строку, имеющую синюю или желтую. Будет ли этот запрос использовать индекс gin? Если нет, как я могу сделать этот запрос с индексом?
4b9b3361

Ответ 1

Почему бы не проверить и не увидеть?

regress=> SET enable_seqscan  = off;
SET

regress=> explain select * from things where 'blue' = ANY (tags);
                                QUERY PLAN                                 
---------------------------------------------------------------------------
 Seq Scan on things  (cost=10000000000.00..10000000037.67 rows=6 width=36)
   Filter: ('blue'::text = ANY ((tags)::text[]))
(2 rows)

regress=> explain select * from things where tags <@ '{"blue"}';
                                     QUERY PLAN                                     
------------------------------------------------------------------------------------
 Bitmap Heap Scan on things  (cost=12.05..21.52 rows=6 width=36)
   Recheck Cond: (tags <@ '{blue}'::character varying[])
   ->  Bitmap Index Scan on index_things_on_tags  (cost=0.00..12.05 rows=6 width=0)
         Index Cond: (tags <@ '{blue}'::character varying[])
(4 rows)

regress=> explain select * from things where '{"blue","yellow"}' && tags;
                                     QUERY PLAN                                      
-------------------------------------------------------------------------------------
 Bitmap Heap Scan on things  (cost=12.10..22.78 rows=12 width=36)
   Recheck Cond: ('{blue,yellow}'::character varying[] && tags)
   ->  Bitmap Index Scan on index_things_on_tags  (cost=0.00..12.09 rows=12 width=0)
         Index Cond: ('{blue,yellow}'::character varying[] && tags)
(4 rows)

Итак, Pg использует индекс для запросов && и <@, но не для = ANY (...).

Я уверен, что можно было бы научить Pg преобразовать x = ANY (y) в ARRAY[x] @> y, но на данный момент это не так.

Что 2 делает именно то, что вы говорите, что хотите. Проверьте, является ли "синий" одним из тегов. Это не тест равенства, это тест на членство.