🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# F.18\. intarray `intarray`模块为操作整数的null-free数组提供一些有用的函数和操作符。 也支持使用其中的一些操作符执行索引搜索。 如果提供的数组包含任何空元素,那么所有这些操作符都将抛出一个错误。 这些操作符中的一些只对一维数组敏感。尽管他们将接受多个维数的输入数组, 数据被按照存储的顺序当做一维数组。 ## F.18.1\. `intarray` 函数和操作符 `intarray`模块提供的函数显示在[Table F-8](#calibre_link-564)里, 操作符显示在[Table F-9](#calibre_link-565)里。 **Table F-8\. `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}` | **Table F-9\. `intarray` 操作符** | 操作符 | 返回 | 描述 | | --- | --- | --- | | `int[] && int[]` | `boolean` | 重复 — 如果数组至少有一个共同元素则为`true` | | `int[] @&gt; int[]` | `boolean` | 包含 — 如果左边的数组包含右边的数组则为`true` | | `int[] &lt;@ int[]` | `boolean` | 包含于 — 如果左边的数组包含于右边的数组则为`true` | | `# int[]` | `int` | 数组中元素的个数 | | `int[] # int` | `int` | 索引 (和`idx` 函数相同) | | `int[] + int` | `int[]` | 将元素推入数组中(将元素添加到数组的末尾) | | `int[] + int[]` | `int[]` | 数组串联(右边的数组添加到左边的数组的后面) | | `int[] - int` | `int[]` | 删除匹配右边数组中元素的项 | | `int[] - int[]` | `int[]` | 从左边数组中删除右边数组中的元素 | | `int[] &#124; int` | `int[]` | 参数的并集 | | `int[] &#124; int[]` | `int[]` | 数组的并集 | | `int[] & int[]` | `int[]` | 数组的交集 | | `int[] @@ query_int` | `boolean` | 如果数组满足查询则为`true` (见下文) | | `query_int ~~ int[]` | `boolean` | 如果数组满足查询则为`true` (`@@`的交换子) | (PostgreSQL 8.2之前,包含操作符`@&gt;`和`&lt;@` 分别称为`@` 和 `~`。这些名字仍然可以使用,但是已经废弃了并且最终会被撤销。 请注意,旧的名字从大会移除,之前跟随着核心几何数据类型!) 操作符`&&`, `@&gt;` 和 `&lt;@`等同于 PostgreSQL同名的内建操作符,除了它们只工作于整数数组不包含空值, 而内建操作符工作于任意数组类型。这个限制使它们在任何情况下都比内建操作符快的多。 `@@` 和 `~~`操作符测试一个数组是否满足一个_query_, 该查询表示为一个专门的数据类型`query_int`的值。_query_ 由针对数组元素检查的整数值组成,可能混合使用操作符`&` (与), `|` (或), 和 `!` (非)。在需要时可以使用括号。 例如,查询`1&(2|3)`匹配包含1也包含2或3的数组。 ## F.18.2\. 索引支持 `intarray`为`&&`, `@&gt;`, `&lt;@`, 和 `@@`操作符还有普通数组相等提供索引支持, 提供两个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 (`&lt;[teodor@sigaev.ru](mailto:teodor@sigaev.ru)&gt;`)和 Oleg Bartunov (`&lt;[oleg@sai.msu.su](mailto:oleg@sai.msu.su)&gt;`)完成的。参阅 [http://www.sai.msu.su/~megera/postgres/gist/](http://www.sai.msu.su/~megera/postgres/gist/)获取额外的信息。 Andrey Oktyabrski在添加新的函数和操作符上做了一个伟大的工作。