2017-08-20 41 views
0

SQL:postgres:为什么这个查询不使用数组值的GIN索引?

CREATE TEMPORARY TABLE objs (obj_id integer); 
CREATE TEMPORARY TABLE sets (obj_id integer[], somecount smallint); 

INSERT INTO objs SELECT generate_series(0,10000); 
INSERT INTO sets 
    SELECT ARRAY[p1.obj_id, p2.obj_id,p3.obj_id], generate_series(0,100) 
    FROM objs as p1 
    CROSS JOIN objs AS p2 
    CROSS JOIN objs AS p3 
    WHERE p2.obj_id = p1.obj_id + 1 AND p3.obj_id = p2.obj_id + 1; 

CREATE INDEX ON sets USING GIN(obj_id); 
SET enable_seqscan = off; 
EXPLAIN ANALYZE SELECT * FROM sets WHERE obj_id @> ARRAY[1,2]::integer[]; 

产量:

             QUERY PLAN              
------------------------------------------------------------------------------------------------------------------------ 
Seq Scan on sets (cost=10000000000.00..10000021039.74 rows=25 width=34) (actual time=0.037..333.496 rows=202 loops=1) 
    Filter: (obj_id @> '{1,2}'::integer[]) 
    Rows Removed by Filter: 1009697 
Planning time: 0.727 ms 
Execution time: 333.529 ms 
(5 rows) 

这是为什么做一个扫描序列,而不是使用索引?

UPDATE

我的服务器上一个数据库运行这个使用上的索引位图堆扫描(太棒了!),并运行它的另一个不(嘘!),我不知道为什么。相同的服务器,不同的数据

+0

Postgres的引擎可能会作出不同的决定基于数据。序列扫描的执行时间是否显着较慢? 此外,是否有必要使用整数数组?为什么不添加一张桌子? Postgres的建立是为了处理表和外键而不是数组。 – marksiemers

回答

1

postgres扩展intarray安装在使用顺序扫描的数据库中,它正在破坏@>运算符。三种选择:

  1. 将呼叫更改为OPERATOR([email protected]>)在GIN索引中使用。

  2. 创建使用gin__int_ops选项索引:CREATE INDEX ON sets USING GIN(obj_id gin__int_ops);

  3. 删除intarray扩展(但我​​需要它在其他地方,所以没了)

相关问题