重新思考数据类型

来自 PostgreSQL wiki
跳转到导航跳转到搜索

重新思考数据类型

当前,PostgreSQL 中的一个类型实际上就只是那一些类型输入/输出函数以及一些关于存储的详细信息而已。对这些类型的任何操作符与该定义都毫不相干。这带来了各种怪异的事情,例如为给定类型查找 B 树索引方法来确定该类型是否可排序。

问题本质上在于,有序、哈希和相等之类的属性是一个类型的属性,而本来真正应该发生的情况是,B 树索引类应该使用该类型本身的属性来构建自身,而不是反过来。

但是,情况比这更加复杂:一个类型可以用多种方法来排序、哈希或测试相等性。明显的例子是字符串,但你可以想出多种方法来对点进行排序,其中所有方法都适用于不同的用途。

描述这些的其中一种方式是“校对”,但一般在提到字符串时会使用该术语。数学术语可能是“有序集合”。

优点

自动创建操作符类和操作符

虽然上述有点抽象,但是有很多好处需要以这种方式考虑类型。

例如,如果作为类型定义的一部分,你可以提供具有以下属性的顺序函数和哈希函数

order: type × type → integer
order(a,b) < 0  <=>  a < b
order(a,b) = 0  <=>  a = b
order(a,b) > 0  <=>  a > b
hash: type → integer
a = b  implies  hash(a) = hash(b)

然后你可以自动创建一个一致的比较操作符集(<,<=,=,>=,>)、一个 B 树操作符类和一个哈希操作符类。

当然,有无顺序或散列都是完全可选的。例如,如果没有散列函数,就不能构建散列索引。唯一节点将能够使用 order() 或 hash() 函数,然而,可以假设计算散列函数比确定顺序的速度更快。

重要的说明:“相等”一词并不一定意味着二个值完全相同。严格来说,一个相等操作符将一个集合分成一些等价类。所以,使用一个顺序函数规定字符串“Hello”和“héllo”相同,这是完全合理的。只要是始终如一即可。

排序键

对大量的数据进行排序所涉及的一个问题在于,需要大约 n*log(n) 的比较操作。在 PostgreSQL 中调用函数并不是很便宜,并且在比较诸如字符串等对象时,开销将变得非常大。但是,如果你考虑上述类似于有序集合的排序,则有一个备选方法。

你需要做的就是提供一个具有以下属性的排序键函数

sortkey: type → integer
sortkey(a) < sortkey(b)   implies a < b

请注意,这比哈希函数更加严格的定义,因此并非所有类型都能够提供它。然而,如果存在,则可以用来显著加快排序速度。当前,该代码对第一个数据项进行了专门处理,但将其直接存储,而不是作为元组的一部分。排序键是一种更紧凑的表现形式,其优点是可以进行比较而大多数情况下无需调用比较函数。相反,我们首先比较整数,并且仅在相等的情况下才会调用实际比较函数。

需要进行一些测试,以查看这是否比直接为字符串存储排序规则键快。然而,字符串的排序规则键往往是原始字符串大小的 1.5 到 2 倍。然后,排序键将作为整数,取前 4 个字节。

相关内容

此内容与许多其他内容密切相关。例如

  • 由排序节点使用 B 树运算符类,以及由哈希节点使用哈希运算符类。
  • SQL COLLATE 支持真正会引发使用多种方式来对单个数据类型进行排序的问题。
  • SQL 规范正在将“order”的使用推广到许多地方,例如用于窗口函数。对这些内容的适当优化可能需要关于“order”的更高级的概念。

实施

无处。此页面实际上只是关于 PostgreSQL 类型系统可能的未来方向的讨论。