重新思考数据类型
重新思考数据类型
当前,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 类型系统可能的未来方向的讨论。