F.18. intarray
intarray模块提供了一些有用的函数和操作符来操纵不含空值的整数数组。也提供了对使用某些操作符的索引搜索的支持。
如果一个提供的数组中包含任何 NULL 元素,所有这些操作都将抛出一个错误。
很多这些操作只对一维数组有意义。尽管它们将接受更多维数的数组输入,数据将被当作一个按照存储顺序排列的线性数组对待。
F.18.1. intarray 函数和操作符
intarray模块提供的函数被列在表 F-10中,操作符被列在表 F-11中。
表 F-10. intarray 函数
函数 | 返回类型 | 描述 | 例子 | 结果 |
---|---|---|---|---|
icount(int[]) |
int | 数组中元素的数量 | icount('{1,2,3}'::int[]) | 3 |
sort(int[], text dir) |
int[] | 排序数组 — dir必须是asc或desc | sort('{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-11. intarray 操作符
操作符 | 返回 | 描述 |
---|---|---|
int[] && int[] | boolean | 重叠 — 如果数组有至少一个公共元素,则为true |
int[] @> int[] | boolean | 包含 — 如果左数组包含右数组,则为true |
int[] <@ int[] | boolean | 被包含 — 如果左数组被右数组包含,则为true |
# int[] | int | 数组中元素的数目 |
int[] # int | int | 索引(与idx 函数相同) |
int[] + int | int[] | 把元素推到数组中(增加到数组末尾) |
int[] + int[] | int[] | 数组串接(把右数组增加到左数组的末尾) |
int[] - int | int[] | 从数组中移除匹配右参数的项 |
int[] - int[] | int[] | 从左数组中移除右数组的元素 |
int[] | int | int[] | 参数的联合 |
int[] | int[] | int[] | 数组的联合 |
int[] & int[] | int[] | 数组的交 |
int[] @@ query_int | boolean | 如果数组满足查询(见下文),则为true |
query_int ~~ int[] | boolean | 如果数组满足查询(@@交换子),则为true |
(在 PostgreSQL 8.2 之前,包含操作符@>和<@分别被称为@和~。这些名称仍然有效,但是已被弃用并且将最终被移除。注意旧名称与核心几何数据类型之前所遵循的习惯相反!)
操作符&&、@>和<@等效于PostgreSQL的内建同名操作符,不过它们只能在不含空值的整数数组上工作,而内建的操作符可以对任何数组类型工作。这种限制使它们在很多情况下比内建操作符更快。
@@和~~操作符测试一个数组是否满足一个query,它被表示成一种特殊数据类型query_int的一个值。一个由整数值组成的查询会被针对数组的元素检查,可能会组合使用操作符&(AND)、|(OR)以及!(NOT)。根据需要可以使用圆括号。例如,查询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 的相对性能特点, 这将在其他地方讨论。
F.18.3. 例子
-- 一个消息可以在一个或多个"小节"中
CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...);
-- 创建专门的索引
CREATE INDEX message_rdtree_idx ON message USING GIST (sections gist__int_ops);
-- 选择小节 1 或 2 中的消息 - OVERLAP 操作符
SELECT message.mid FROM message WHERE message.sections && '{1,2}';
-- 选择小节 1 和 2 中的消息 - 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包含有一个基准测试套件,可以针对 一个安装好的PostgreSQL服务器运行这个套件(还要求安装 DBD::Pg)。要运行测试基准:
cd .../contrib/intarray/bench createdb TEST psql -c "CREATE EXTENSION intarray" TEST ./create_test.pl | psql TEST ./bench.pl
bench.pl脚本有多个选项,当它不使用任何参数运行时会显示这些选项。
F.18.5. 作者
所有工作由 Teodor Sigaev(<[email protected]>
)和 Oleg Bartunov(<[email protected]>
)完成。更多信息请见Http://www.sai.msu.su/~megera/postgres/gist/。Andrey Oktyabrski 完成了一项伟大的工作,他增加了新的函数和操作。