I have a postgres array column with a gin index:
CREATE TABLE things (
id integer NOT NULL,
tags character varying(255)[]
);
CREATE INDEX index_things_on_tags ON things USING gin (tags);
There are a few ways to check for the presence of an element in the column, using various array operators. Here are the ones I've seen:
select * from things where 'blue' = ANY (tags)
select * from things where tags <@ '{"blue"}'
select * from things where '{"blue","yellow"}' && tags;
In postgres 9.3:
GIN always stores and searches for keys, not item values per se. A GIN index stores a set of (key, posting list) pairs, where a posting list is a set of row IDs in which the key occurs. The same row ID can appear in multiple posting lists, since an item can contain more than one key.
Fortunately, PostgreSQL has the ability to combine multiple indexes (including multiple uses of the same index) to handle cases that cannot be implemented by single index scans. The system can form AND and OR conditions across several index scans.
An Index is the structure or object by which we can retrieve specific rows or data faster. Indexes can be created using one or multiple columns or by using the partial data depending on your query requirement conditions. Index will create a pointer to the actual rows in the specified table.
Why not test and see?
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)
So Pg is using the index for the &&
and <@
queries, but not for = ANY (...)
.
I'm sure it'd be possible to teach Pg to transform x = ANY (y)
into ARRAY[x] @> y
, but it doesn't at the moment.
What 2 does is exactly what you say you want. Test if "blue" is one of the tags. It's not an equality test, it's a membership test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With