↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3
预发布版本文档。 PostgreSQL 19beta4 为测试版本,最终发布内容可能有所不同。

F.10. cube — 多维立方体数据类型 #

该模块实现了用于表示多维立方体的 cube 数据类型。

该模块被认为是“受信任的”,也就是说,它可以由在当前数据库上具有 CREATE 权限的非超级用户安装。

F.10.1. 语法 #

表 F.1 展示了 cube 类型合法的外部表示。x、y 等表示浮点数。

表 F.1. cube 外部表示

外部语法含义
x一个一维点(或者长度为零的一维区间)
(x)同上
x1,x2,...,xnn 维空间中的一个点,在内部表示为零体积立方体
(x1,x2,...,xn)同上
(x),(y)一个从 x 开始、到 y 结束的一维区间,反过来也可以;顺序无关紧要
[(x),(y)]同上
(x1,...,xn),(y1,...,yn)一个 n 维立方体,由一对对角相对的角点表示
[(x1,...,xn),(y1,...,yn)]同上

立方体的两个对角点以何种顺序输入都无关紧要。必要时,cube 函数会自动交换这些值,以创建统一的“左下角 — 右上角”内部表示。当两个角点重合时,cube 只存储其中一个角点,并附带一个“是点”标志,以避免浪费空间。

输入时会忽略空白字符,因此 [(x),(y)] 与 [ ( x ), ( y ) ] 相同。

F.10.2. 精度 #

值在内部以 64 位浮点数存储。这意味着有效数字超过大约 16 位的数值会被截断。

F.10.3. 用法 #

表 F.2 展示了为 cube 类型提供的专用操作符。

表 F.2. cube 操作符

操作符

描述

cube && cube → boolean

两个立方体是否重叠?

cube @> cube → boolean

第一个立方体是否包含第二个立方体?

cube <@ cube → boolean

第一个立方体是否包含在第二个立方体中?

cube -> integer → float8

提取立方体的第 n 个坐标值(从 1 开始计数)。

cube ~> integer → float8

提取立方体的第 n 个坐标值,计数方式如下:n = 2 * k - 1 表示第 k 维的下界,n = 2 * k 表示第 k 维的上界。n 为负时,返回对应正编号所取坐标值的相反数。该操作符专为支持 KNN-GiST 而设计。

cube <-> cube → float8

计算两个立方体之间的欧几里得距离。

cube <#> cube → float8

计算两个立方体之间的出租车(L-1 度量)距离。

cube <=> cube → float8

计算两个立方体之间的切比雪夫(L-inf 度量)距离。


除了上述操作符外,表 9.1 中列出的常见比较操作符也可用于 cube 类型。这些操作符先比较第一个坐标;如果两者相等,再比较第二个坐标,依此类推。它们主要是为了支持 cube 的 B-树索引操作符类而存在;例如,如果你希望在 cube 列上定义 UNIQUE 约束,这会很有用。除此之外,这种排序在实践中并没有太大用处。

cube 模块还为 cube 值提供了一个 GiST 索引操作符类。cube GiST 索引可用于在 WHERE 子句中使用 =、&&、@> 和<@操作符搜索值。

此外,cube GiST 索引还可用于在 ORDER BY 子句中借助度量操作符 <->、<#> 和 <=> 查找最近邻。例如,三维点 (0.5, 0.5, 0.5) 的最近邻可以用下面的查询高效地找到:

SELECT c FROM test ORDER BY c <-> cube(ARRAY[0.5, 0.5, 0.5]) LIMIT 1;

~> 操作符也可以这样使用,以便高效地检索按选定坐标排序后的前几个值。例如,要获得按第一个坐标(左下角)升序排列的前几个立方体,可以使用下面的查询:

SELECT c FROM test ORDER BY c ~> 1 LIMIT 5;

要获得按右上角第一个坐标降序排列的二维立方体,可以使用:

SELECT c FROM test ORDER BY c ~> 3 DESC LIMIT 5;

表 F.3 展示了可用函数。

表 F.3. cube 函数

函数

描述

示例

cube ( float8 ) → cube

创建一个一维立方体,其两个坐标相同。

cube(1) → (1)

cube ( float8, float8 ) → cube

创建一个一维立方体。

cube(1, 2) → (1),(2)

cube ( float8[] ) → cube

根据数组定义的坐标创建一个零体积立方体。

cube(ARRAY[1,2,3]) → (1, 2, 3)

cube ( float8[], float8[] ) → cube

创建一个立方体,其右上角和左下角坐标由这两个数组定义,这两个数组必须等长。

cube(ARRAY[1,2], ARRAY[3,4]) → (1, 2),(3, 4)

cube ( cube, float8 ) → cube

通过向现有立方体增加一个维度来创建新的立方体,新坐标的两个端点取相同的值。这可用于根据计算得到的值逐步构建立方体。

cube('(1,2),(3,4)'::cube, 5) → (1, 2, 5),(3, 4, 5)

cube ( cube, float8, float8 ) → cube

通过向现有立方体增加一个维度来创建新的立方体。这可用于根据计算得到的值逐步构建立方体。

cube('(1,2),(3,4)'::cube, 5, 6) → (1, 2, 5),(3, 4, 6)

cube_dim ( cube ) → integer

返回立方体的维数。

cube_dim('(1,2),(3,4)') → 2

cube_ll_coord ( cube, integer ) → float8

返回立方体左下角的第 n 个坐标值。

cube_ll_coord('(1,2),(3,4)', 2) → 2

cube_ur_coord ( cube, integer ) → float8

返回立方体右上角的第 n 个坐标值。

cube_ur_coord('(1,2),(3,4)', 2) → 4

cube_is_point ( cube ) → boolean

如果立方体是一个点,也就是定义它的两个角相同,则返回真。

cube_is_point(cube(1,1)) → t

cube_distance ( cube, cube ) → float8

返回两个立方体之间的距离。如果两个立方体都是点,这就是普通的距离函数。

cube_distance('(1,2)', '(3,4)') → 2.8284271247461903

cube_subset ( cube, integer[] ) → cube

根据数组中给出的维度索引列表,从现有立方体创建一个新立方体。可用于提取单个维度的端点、删除维度,或者按需要重新排列维度。

cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) → (3),(7)

cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) → (5, 3, 1, 1),(8, 7, 6, 6)

cube_union ( cube, cube ) → cube

生成两个立方体的并集。

cube_union('(1,2)', '(3,4)') → (1, 2),(3, 4)

cube_inter ( cube, cube ) → cube

生成两个立方体的交集。

cube_inter('(1,2)', '(3,4)') → (3, 4),(1, 2)

cube_enlarge ( c cube, r double, n integer ) → cube

以指定的半径 r 在至少 n 个维度上增大立方体的尺寸。如果半径为负,则会改为收缩立方体。所有已定义维度都会按半径 r 调整。左下角坐标减去 r,右上角坐标加上 r。如果某个左下角坐标增加到超过对应的右上角坐标(这只会在 r < 0 时发生),则两个坐标都会被设为它们的平均值。如果 n 大于已定义维度数且立方体正在增大(r > 0),则会增加额外的维度,使总维度数达到 n;这些额外坐标的初始值为 0。该函数适合为某个点构造边界框,以便搜索附近的点。

cube_enlarge('(1,2),(3,4)', 0.5, 3) → (0.5, 1.5, -0.5),(3.5, 4.5, 0.5)


F.10.4. 默认规则 #

下面这个并集:

SELECT cube_union('(0,5,2),(2,3,1)', '0');
cube_union
-------------------
(0, 0, 0),(2, 5, 2)
(1 row)

并不违背常识,下面这个交集也是如此:

SELECT cube_inter('(0,-1),(1,1)', '(-2),(2)');
cube_inter
-------------
(0, 0),(1, 0)
(1 row)

在所有对不同维度立方体执行的二元操作中,都假定维度较低的那个是一个笛卡尔投影,也就是说,在字符串表示中省略的坐标位置上补 0。上面的例子等价于:

cube_union('(0,5,2),(2,3,1)','(0,0,0),(0,0,0)');
cube_inter('(0,-1),(1,1)','(-2,0),(2,0)');

下面的包含谓词使用的是点语法,但实际上第二个参数在内部表示为一个立方体。这种语法使我们无须单独定义点类型以及用于 (box,point) 谓词的函数。

SELECT cube_contains('(0,0),(1,1)', '0.5,0.5');
cube_contains
--------------
t
(1 row)

F.10.5. 注解 #

有关用法示例,请参见回归测试 sql/cube.sql。

为了避免用户轻易把事情弄坏,立方体的维数上限被设为 100。如果需要更大的值,可在 cubedata.h 中修改该限制。

F.10.6. 致谢 #

原作者:Gene Selkov, Jr. ,阿贡国家实验室数学与计算机科学部。

我首先要感谢 Joe Hellerstein 教授 (https://dsf.berkeley.edu/jmh/),他为我阐明了 GiST (http://gist.cs.berkeley.edu/) 的要旨;也感谢他曾经的学生 Andy Dong 为 Illustra 编写了示例。我同样感谢过去和现在所有的 Postgres 开发者,他们使我得以创造自己的世界并在其中不受打扰地生活。我还要感谢阿贡实验室以及美国能源部,多年来始终如一地支持我的数据库研究。

Bruno Wolff III 在 2002 年 8 月和 9 月对该软件包做了一些小更新,包括将精度从单精度改为双精度,并增加了一些新函数。

Joshua Reich 在 2006 年 7 月做了进一步更新。这些更新包括加入 cube(float8[], float8[]),并清理代码,使其使用 V1 调用协议而不是已废弃的 V0 协议。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.