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

时间:2014-02-28 21:27:51

标签: sql postgresql

我有一个带有杜松子酒索引的postgres数组列:

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

CREATE INDEX index_things_on_tags ON things USING gin (tags);

有几种方法可以使用各种数组运算符检查列中是否存在元素。以下是我见过的那些:

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

    • 第一个会使用杜松子酒索引吗?
    • 我很确定第二个会使用索引。但是,它与第一个不同。它不允许我检查蓝色是否是标签之一,它需要我指定确切的数组。有没有办法让2中的语法风格达到1实现的目的?
    • 在第三个中,我希望任何一行都有蓝色或黄色。这个查询会使用杜松子酒索引吗?如果没有,我如何使用索引进行此查询?

1 个答案:

答案 0 :(得分:19)

为什么不测试看?

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你做的正是你想要的。测试“蓝色”是否是标签之一。这不是一个平等测试,它是一个会员资格测试。