索引postgresql数组列以进行大于/小于比较?
Posted
技术标签:
【中文标题】索引postgresql数组列以进行大于/小于比较?【英文标题】:Index a postgresql array column for greater than / less than comparisons? 【发布时间】:2013-11-09 14:56:44 【问题描述】:我可以在 Postgresq 9.1 中索引数组列以支持:
select * from t where 100 < any(a) and 100 > any(a)
其中a
是一个整数数组(其中的行具有一些值,例如90,110
,因此查询不会返回空。)
详情
create table t ( a integer[] )
insert into t values ('90,110'::integer[])
在上述查询上运行 explain analyze
会产生:
Seq Scan on t (cost=0.00..1.07 rows=2 width=32) (actual time=0.009..0.009 rows=1 loops=1)
Filter: ((100 < ANY (a)) AND (100 > ANY (a)))
Total runtime: 0.023 ms
背景
以下问题描述了一种方法,但似乎不适用于非固定长度数组:
Can PostgreSQL index array columns?
Postgres docs 描述了内置的 GIN 运算符,但它们似乎不支持大于/小于运算:
例如,PostgreSQL 的标准发行版包括 GIN 一维数组的运算符类,支持索引 使用这些运算符的查询:、=、&&
【问题讨论】:
EXPLAIN ANALYZE
和架构定义,以及 PostgreSQL 版本。
问题不清楚。 select 100 < '90,110'::int[];
产生错误。也许您实际上正在寻找范围类型? select 100 <@ '[90,110]'::int4range;
@CraigRinger 已更新,谢谢。
@Denis 更新了问题,谢谢。一般来说,可以在本专栏中找到任意大小的整数列表——不仅仅是边界。并且可以查询任意数量的相等和/或更大/更少的比较。
所以......您正在尝试为“此数组中的任何元素大于值'a'任何元素(可能是不同的元素)小于值' b'" ?
【参考方案1】:
您可以在一个函数上创建一个索引,该函数将您的列的边界作为 int4range 返回:
create or replace function intarray2int4range(arr int[]) returns int4range as $$
select int4range(min(val), max(val) + 1) from unnest(arr) as val;
$$ language sql immutable;
例子:
create table t (a int[]);
insert into t
select array[i - j % 5, i - j % 3, i, i + j % 3, i + j % 5]
from generate_series(0,1000) i, generate_series(0,100) j;
create index on t using gist(a);
vacuum analyze t;
产量:
explain analyze select * from t where 20 <@ intarray2int4range(a) limit 5;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.53..16.55 rows=5 width=41) (actual time=0.056..0.060 rows=5 loops=1)
-> Index Scan using t_intarray2int4range_idx on t (cost=0.53..1669.65 rows=521 width=41) (actual time=0.055..0.058 rows=5 loops=1)
Index Cond: (20 <@ intarray2int4range(a))
Total runtime: 0.095 ms
(4 rows)
它还允许您运行类似的查询来扫描值范围:
explain analyze select * from t where '[20,30]'::int4range && intarray2int4range(a) limit 5;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.53..11.82 rows=5 width=41) (actual time=0.125..0.130 rows=5 loops=1)
-> Index Scan using t_intarray2int4range_idx on t (cost=0.53..3499.66 rows=1550 width=41) (actual time=0.123..0.126 rows=5 loops=1)
Index Cond: ('[20,31)'::int4range && intarray2int4range(a))
Total runtime: 0.169 ms
(4 rows)
【讨论】:
以上是关于索引postgresql数组列以进行大于/小于比较?的主要内容,如果未能解决你的问题,请参考以下文章
插入数组列表时,索引(从零开始)必须大于或等于零且小于参数列表的大小