I can't find a definite answer to this question in the documentation. If a column is an array type, will all the entered values be individually indexed?
I created a simple table with one int[]
column, and put a unique index on it. I noticed that I couldn't add the same array of ints, which leads me to believe the index is a composite of the array items, not an index of each item.
INSERT INTO "Test"."Test" VALUES ('{10, 15, 20}');
INSERT INTO "Test"."Test" VALUES ('{10, 20, 30}');
SELECT * FROM "Test"."Test" WHERE 20 = ANY ("Column1");
Is the index helping this query?
@Tregoreg raised a question in the comment to his offered bounty:
@Frank's accepted answer tells you to use array operators, which is still correct for Postgres 10. The manual:
The complete list of built-in operator classes for GIN indexes in the standard distribution is here.
In Postgres indexes are bound to operators, not data types or functions or anything else. That's a heritage from the original Berkeley design of Postgres and very hard to change now. And it's generally working just fine. Here is a thread on pgsql-bugs with Tom Lane commenting on this.
The indexed expression must be to the left of the operator. For most operators (including all of the above) the query planner can achieve this by flipping operands if you place the indexed expression to the right - given that a
COMMUTATOR
has been defined. TheANY
construct can be used in combination with various operators and is not an operator itself. When used asconstant = ANY (array_expression)
only indexes supporting the=
operator on array elements would qualify and we would need a commutator for= ANY()
. GIN indexes are out.Postgres is not currently smart enough to derive a GIN-indexable expression from it. For starters,
constant = ANY (array_expression)
is not completely equivalent toarray_expression @> ARRAY[constant]
. Array operators return an error if any NULL elements are involved, while theANY
construct can deal with NULL on either side. And there are different results for data type mismatches.Related answers:
Check if value exists in Postgres array
Index for finding an element in a JSON array
SQLAlchemy: how to filter on PgArray column types?
Can IS DISTINCT FROM be combined with ANY or ALL somehow?
Asides
While working with
integer
arrays (int4
, notint2
orint8
) withoutNULL
values (like your example implies) consider the additional moduleintarray
, that provides specialized, faster operators and index support. See:As for the
UNIQUE
constraint in your question that went unanswered: That's implemented with a btree index on the whole array value (like you suspected) and does not help with the search for elements at all. Details:Yes you can index an array, but you have to use the array operators and the GIN-index type.
Example:
Result:
Noteit appears that in many cases the gin__int_ops option is required
I have not yet seen a case where it would work with the && and @> operator without the gin__int_ops options
It's now possible to index the individual array elements. For example:
This works on at least Postgres 9.2.1. Note that you need to build a separate index for each array index, in my example I only indexed the first element.