F.18. intarray

intarray模块为操作整数的null-free数组提供一些有用的函数和操作符。 也支持使用其中的一些操作符执行索引搜索。

如果提供的数组包含任何空元素,那么所有这些操作符都将抛出一个错误。

这些操作符中的一些只对一维数组敏感。尽管他们将接受多个维数的输入数组, 数据被按照存储的顺序当做一维数组。

F.18.1. intarray 函数和操作符

intarray模块提供的函数显示在表 F-8里, 操作符显示在表 F-9里。

表 F-8. intarray 函数

函数返回类型描述示例结果
icount(int[])int数组中元素的个数icount('{1,2,3}'::int[])3
sort(int[], text dir)int[]给数组排序 — dir 必须为 ascdescsort('{1,2,3}'::int[], 'desc'){3,2,1}
sort(int[])int[]以升序顺序排序sort(array[11,77,44]){11,44,77}
sort_asc(int[])int[]以升序顺序排序
sort_desc(int[])int[]以降序顺序排序
uniq(int[])int[]删除相邻的重复uniq(sort('{1,2,3,2,1}'::int[])){1,2,3}
idx(int[], int item)int匹配item的第一个元素中的索引 (如果没有则为0)idx(array[11,22,33,22,11], 22)2
subarray(int[], int start, int len)int[]start 位置开始的, len 个元素的数组的一部分subarray('{1,2,3,2,1}'::int[], 2, 3){2,3,2}
subarray(int[], int start)int[]start 位置开始的数组的一部分subarray('{1,2,3,2,1}'::int[], 2){2,3,2,1}
intset(int)int[]制作单个元素的数组intset(42){42}

表 F-9. intarray 操作符

操作符返回描述
int[] && int[]boolean重复 — 如果数组至少有一个共同元素则为true
int[] @> int[]boolean包含 — 如果左边的数组包含右边的数组则为true
int[] <@ int[]boolean包含于 — 如果左边的数组包含于右边的数组则为true
# int[]int数组中元素的个数
int[] # intint索引 (和idx 函数相同)
int[] + intint[]将元素推入数组中(将元素添加到数组的末尾)
int[] + int[] int[]数组串联(右边的数组添加到左边的数组的后面)
int[] - intint[]删除匹配右边数组中元素的项
int[] - int[]int[]从左边数组中删除右边数组中的元素
int[] | intint[]参数的并集
int[] | int[]int[]数组的并集
int[] & int[]int[]数组的交集
int[] @@ query_intboolean如果数组满足查询则为true (见下文)
query_int ~~ int[]boolean如果数组满足查询则为true (@@的交换子)

(PostgreSQL 8.2之前,包含操作符@><@ 分别称为@~。这些名字仍然可以使用,但是已经废弃了并且最终会被撤销。 请注意,旧的名字从大会移除,之前跟随着核心几何数据类型!)

操作符&&, @><@等同于 PostgreSQL同名的内建操作符,除了它们只工作于整数数组不包含空值, 而内建操作符工作于任意数组类型。这个限制使它们在任何情况下都比内建操作符快的多。

@@~~操作符测试一个数组是否满足一个query, 该查询表示为一个专门的数据类型query_int的值。query 由针对数组元素检查的整数值组成,可能混合使用操作符& (与), | (或), 和 ! (非)。在需要时可以使用括号。 例如,查询1&(2|3)匹配包含1也包含2或3的数组。

F.18.2. 索引支持

intarray&&, @>, <@, 和 @@操作符还有普通数组相等提供索引支持,

提供两个GiST索引操作符类:gist__int_ops(缺省使用) 适合于小到中等的数据集,而gist__intbig_ops 使用一个大的签名并且更适合于索引大的数据集(也就是, 包含大量不同数组值的字段)。该实现使用一个RD树数据结构和内建的有损压缩。

还有一个非缺省的GIN操作符类gin__int_ops支持相同的操作符。

GiST和GIN索引的选择取决于GiST和GIN相关的性能特性,这个在别的地方讨论。 一般来说,GIN索引比GiST索引搜索起来更快一些,而建立或更新要慢一些; 所以GIN更适合于静态数据,而GiST更适合于经常更新的数据。

F.18.3. 示例

-- 一个message可以在一个或多个"sections"中
CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...);

-- 创建专门的索引
CREATE INDEX message_rdtree_idx ON message USING GIST (sections gist__int_ops);

-- 在section 1或2中选择message -OVERLAP操作符
SELECT message.mid FROM message WHERE message.sections && '{1,2}';

-- 在section 1和2中选择message -CONTAINS操作符
SELECT message.mid FROM message WHERE message.sections @> '{1,2}';

-- 相同的,使用QUERY操作符
SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int;

F.18.4. 基准

源目录contrib/intarray/bench包含一个基准测试套件。运行:

cd .../bench
createdb TEST
psql TEST < ../_int.sql
./create_test.pl | psql TEST
./bench.pl

bench.pl脚本有许多选项,当它不带任何参数的运行时显示。

F.18.5. 作者

所有工作都是Teodor Sigaev ()和 Oleg Bartunov ()完成的。参阅 http://www.sai.msu.su/~megera/postgres/gist/获取额外的信息。 Andrey Oktyabrski在添加新的函数和操作符上做了一个伟大的工作。