Postgresql 中文操作指南
F.39. seg — a datatype for line segments or floating point intervals #
此模块实现了表示线段或浮点间隔的数据类型 seg。_seg_可以在区间端点表示不确定性,使其在表示实验室测量时特别有用。
此模块被认为是“受信任的”,也就是说,它可以由在当前数据库上具有 CREATE 权限的非超级用户安装。
F.39.1. Rationale #
测量结果的几何形状通常比数值连续统一体中的一个点的几何形状更加复杂。测量结果通常是该连续区间的某个分支,其边界有点模糊。测量结果作为区间出现,原因在于存在模糊性和随机性,也可能是因为正在测量的值本来就是一个区间,它表示了某种条件,比如蛋白质的稳定温度范围。
仅凭常识,将这种数据存储为区间而非数字对似乎更加方便。在实践中,在大多数应用中,这样做甚至会更加高效。
进一步遵循常识思路,边界模糊性表明使用传统的数字数据类型会导致某些信息丢失。考虑一下这种情况:你的仪器读数为 6.50,你将此读数输入数据库。当你获取它时,你会得到什么?请看:
test=> select 6.50 :: float8 as "pH";
pH
---
6.5
(1 row)
在测量领域中,6.50 与 6.5 不同。有时可能会有根本性的不同。实验人员通常会写下(并发布)他们信任的数字。6.50 实际上是包含在更大且更模糊的区间 6.5 中的模糊区间,它们之间的唯一共同特征是(可能)它们的中心点。我们当然不希望这些不同的数据项看起来是一样的。
结论?最好拥有特殊的数据类型,以尽可能可变的精度记录区间的边界。可变的意思是,每个数据元素都记录自己的精度。
请查看以下内容:
test=> select '6.25 .. 6.50'::seg as "pH";
pH
------------
6.25 .. 6.50
(1 row)
F.39.2. Syntax #
区间的外在表现形式使用连接了范围操作符 (.._或 _…) 的一个或两个浮点数形成。或者,它可以指定为中心点加上或减去一个偏差。可选确定性指标 (<、>_或 _~) 也可以存储。但是,所有内建操作符都会忽略确定性指标。 Table F.28概述了允许的表现形式; Table F.29显示了一些示例。
在 Table F.28中,x、y_和 _delta_表示浮点数。_x_和 _y,但不是 delta,可以在前面加上一个确定性指标。
Table F.28. seg External Representations
x |
Single value (zero-length interval) |
x_ .. _y |
区间 x 至 y |
x_ (+-) _delta |
区间 x - delta 至 x + delta |
_x .._ |
下界为 x 的开区间 |
.. _x_ |
上界为 x 的开区间 |
Table F.29. Examples of Valid seg Input
5.0 |
创建一个零长度片段(一个点,如果你愿意) |
~5.0 |
创建一个零长度片段,并将 ~ 记录在数据中。 seg 操作会忽略 ~ ,但是保留它作为注释。 |
<5.0 |
在 5.0 处创建一个点。 < 被忽略但作为注释保留。 |
>5.0 |
在 5.0 处创建一个点。 > 被忽略但作为注释保留。 |
5(+-)0.3 |
创建一个区间 4.7 .. 5.3 。请注意 (+-) 符号不会保留。 |
50 .. |
所有大于或等于 50 的内容 |
.. 0 |
小于或等于 0 的一切 |
1.5e-2 .. 2E-2 |
创建了一个区间 0.015 .. 0.02 |
1 … 2 |
与 1…​2 、 1 .. 2 或 1..2 相同(范围操作符周围的空格将被忽略) |
因为 … 运算符在数据源中得到了广泛的使用,因此将其允许作为 .. 运算符的备用拼写形式。不幸的是,这造成了解析模糊性:在 0…23 中,并不清楚上限是指 23 还是 0.23。这可以通过要求 seg 输入中所有数字在小数点前至少有一位数字来解决。
作为健全性检查,seg 拒绝下限大于上限的区间,例如 5 .. 2。
F.39.3. Precision #
seg 值在内部存储为 32 位浮点数字对。这意味着,尾数超过 7 位的数字将被截断。
尾数为 7 位或更少的数字保留其原始精度。也就是说,如果你的查询返回 0.00,你可以确定尾随零并非格式化的伪影:它们反映了原始数据的精度。前导零数量不影响精度:数值 0.0067 被认为只有 2 位有效数字。
F.39.4. Usage #
_seg_模块包括 _seg_值的 GiST 索引操作符类。GiST 操作符类支持的操作符显示在 Table F.30中。
Table F.30. Seg GiST Operators
Operator Description |
seg << seg → boolean 第一个 seg 完全位于第二个 seg 左侧?如果 b < c,[a, b] << [c, d] 为 true。 |
seg >> seg → boolean 第一个 seg 完全位于第二个 seg 右侧?如果 a > d,[a, b] >> [c, d] 为 true。 |
seg &< seg → boolean 第一个 seg 是否未延伸到第二个 seg 右侧?如果 b ⇐ d,[a, b] &< [c, d] 为 true。 |
seg &> seg → boolean 第一个 seg 是否未延伸到第二个 seg 左侧?如果 a >= c,[a, b] &> [c, d] 为 true。 |
seg = seg → boolean 这两个 seg 是否相等? |
seg && seg → boolean 这两个 seg 是否重叠? |
seg @> seg → boolean 第一个 seg 是否包含第二个 seg ? |
seg <@ seg → boolean 第一个 seg 是否包含在第二个 seg 中? |
除了上述操作符之外, Table 9.1中显示的常用比较操作符也可用于类型 seg。这些操作首先比较 (a) 和 (c),如果它们相等,则比较 (b) 和 (d)。这在大多数情况下都能产生合理良好的排序,如果您想将 ORDER BY 用于此类型,这将非常有用。
F.39.5. Notes #
有关用法的示例,请参阅回归测试_sql/seg.sql_。
将_(+-)_转换为常规范围的机制在确定边界显着位数时并不能完全准确。例如,如果结果区间包含一个十的幂次,它会向较低边界添加一个额外的位数:
postgres=> select '10(+-)1'::seg as seg;
seg
---------
9.0 .. 11 -- should be: 9 .. 11
R树索引的性能在很大程度上取决于输入值的初始顺序。在_seg_列上对输入表进行排序可能非常有用;参阅 sort-segments.pl 中的脚本以获取示例。
F.39.6. Credits #
原始作者:基因塞尔科夫,Jr. < link:mailto:selkovjr@mcs.anl.gov[selkovjr@mcs.anl.gov]> ,数学和计算机科学分部,阿贡国家实验室。
我要感谢的主要是乔·赫勒斯坦因教授 ( https://dsf.berkeley.edu/jmh/) 阐明了 GiST ( http://gist.cs.berkeley.edu/) 的要点。我还要感谢所有过去和现在的 Postgres 开发人员,他们让我得以创造自己的世界,并在其中不受打扰地生活。我还想向阿贡实验室和美国能源部表示感谢,感谢他们多年来对我数据库研究的大力支持。