PostgreSQL可以索引数组列吗?

在文档中我找不到明确的答案。 如果一个列是一个数组types,所有input的值是否会被单独索引?

我用一个int[]列创build了一个简单的表,并在其上放置了一个唯一的索引。 我注意到我不能添加相同的整数数组,这导致我相信索引是数组项的组合,而不是每个项目的索引。

 INSERT INTO "Test"."Test" VALUES ('{10, 15, 20}'); INSERT INTO "Test"."Test" VALUES ('{10, 20, 30}'); SELECT * FROM "Test"."Test" WHERE 20 = ANY ("Column1"); 

该索引是否有助于查询?

是的,你可以索引一个数组,但你必须使用数组运算符和GIN索引types 。

例:

  CREATE TABLE "Test"("Column1" int[]); INSERT INTO "Test" VALUES ('{10, 15, 20}'); INSERT INTO "Test" VALUES ('{10, 20, 30}'); CREATE INDEX idx_test on "Test" USING GIN ("Column1"); -- To enforce index usage because we have only 2 records for this test... SET enable_seqscan TO off; EXPLAIN ANALYZE SELECT * FROM "Test" WHERE "Column1" @> ARRAY[20]; 

结果:

 Bitmap Heap Scan on "Test" (cost=4.26..8.27 rows=1 width=32) (actual time=0.014..0.015 rows=2 loops=1) Recheck Cond: ("Column1" @> '{20}'::integer[]) -> Bitmap Index Scan on idx_test (cost=0.00..4.26 rows=1 width=0) (actual time=0.009..0.009 rows=2 loops=1) Index Cond: ("Column1" @> '{20}'::integer[]) Total runtime: 0.062 ms 

特雷格雷格在评论中提出了一个问题

我没有find当前的答案工作。 在array-typed列上使用GIN索引不会增加ANY()运算符的性能。 真的没有解决办法吗?

@弗兰克接受的答案告诉你使用数组运算符 ,这在2015年仍然正确的。
每个文档:

PostgreSQL的标准分布包括一维数组的GIN操作符类,它支持使用这些操作符的索引查询:

  <@ @> = && 

标准分配中GIN索引的内置运算符类的完整列表在这里。

在Postgres中, 索引绑定到运算符 ,而不是数据types或函数或其他任何东西。 这是来自Postgres的原始伯克利devise的遗产,现在很难改变。 它通常工作得很好。 这里是一个关于pgsql-bugs的线程,Tom评论这个。

索引expression式必须位于运算符的左侧 。 对于大多数运算符( 包括上述所有内容 ),查询规划器可以通过翻转操作数来实现这一点,如果将索引expression式放在右侧(假定已经定义了COMMUTATORANY结构可以与各种运营商结合使用,而不是运营商本身。 当用作constant = ANY (array_expression)只有在数组元素上支持=运算符的索引才有资格,我们需要一个= ANY()的换向器。 GIN索引已经出来

Postgres目前还不够聪明,从它得到一个GIN可索引的expression式。 对于初学者来说, constant = ANY (array_expression) 并不完全等同array_expression @> ARRAY[constant] 。 如果涉及到任何NULL 元素 ,则数组运算符会返回一个错误,而ANY构造可以在任何一边处理NULL。 数据types不匹配有不同的结果。

相关答案:

  • 检查Postgres数组中是否存在值

  • 在JSON数组中查找元素的索引

  • SQLAlchemy:如何过滤PgArray列types?

  • 可以DISTINCT从任何或所有莫名其妙?


至于你的问题中的UNIQUE约束没有得到答复:这是用整个数组值的btree索引实现的(就像你怀疑的那样),并没有帮助search元素 。 细节:

  • PostgreSQL如何强制使用UNIQUE约束/它使用什么types的索引?

现在可以索引单个数组元素。 例如:

 CREATE TABLE test (foo int[]); INSERT INTO test VALUES ('{1,2,3}'); INSERT INTO test VALUES ('{4,5,6}'); CREATE INDEX test_index on test ((foo[1])); SET enable_seqscan TO off; EXPLAIN ANALYZE SELECT * from test WHERE foo[1]=1; QUERY PLAN ------------------------------------------------------------------------------------------------------------------ Index Scan using test_index on test (cost=0.00..8.27 rows=1 width=32) (actual time=0.070..0.071 rows=1 loops=1) Index Cond: (foo[1] = 1) Total runtime: 0.112 ms (3 rows) 

这至less可以在Postgres 9.2.1上运行。 请注意,您需要为每个数组索引构build一个单独的索引,在我的示例中,我只索引了第一个元素。