SQL:
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)
为什么要进行序列扫描而不使用索引?
更新
在我的服务器上的一个数据库上运行它使用索引上的位图堆扫描(太棒了!)而另一个运行它不会(嘘!)而我不知道为什么。相同的服务器,不同的数据库。
答案 0 :(得分:1)
postgres扩展程序intarray
安装在使用顺序扫描的数据库中,它正在破坏@>
运算符。三个选项:
将调用更改为GIN索引中的OPERATOR(pg_catalog.@>)
。
使用gin__int_ops
选项创建索引:CREATE INDEX ON sets USING GIN(obj_id gin__int_ops);
删除intarray
扩展名(但我在别处需要,所以不要)