简体   繁体   English

如何使用gin索引查询postgres数组?

[英]How does one query a postgres array using the gin index?

I have a postgres array column with a gin index: 我有一个带有杜松子酒索引的postgres数组列:

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: 以下是我见过的:

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

In postgres 9.3: 在postgres 9.3中:

  • Will the first one use the gin index? 第一个会使用杜松子酒指数吗?
  • I'm pretty sure the second one will use the index. 我很确定第二个会使用索引。 However, it is different from the first. 但是,它与第一个不同。 it doesn't allow me to check if blue is one of the tags, it requires me to specify the exact array. 它不允许我检查蓝色是否是标签之一,它需要我指定确切的数组。 Is there a way to make the style of syntax in 2 achieve what 1 is achieving? 有没有办法让2中的语法风格实现1实现的目标?
  • In the third, I want any row that has any one of blue or yellow. 在第三个,我想要任何有蓝色或黄色的行。 Will this query use the gin index? 这个查询会使用杜松子酒索引吗? If not, how can I do this query with an index? 如果没有,我如何使用索引进行此查询?

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 (...) . 所以Pg使用&&<@查询的索引,但不是= 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. 我确信有可能教Pg将x = ANY (y)变换为ARRAY[x] @> y ,但目前还没有。

What 2 does is exactly what you say you want. 2你做的正是你想要的。 Test if "blue" is one of the tags. 测试“蓝色”是否是标签之一。 It's not an equality test, it's a membership test. 这不是一个平等测试,它是一个成员资格测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM