高级PostgreSQL数据类型

2020-05-28 03:51:35

这篇文章是由两部分组成的系列文章的第二部分--在这里阅读第一部分:回到PostgreSQL数据类型的基础。

在上一篇文章中,我分享了一些我在研究PostgreSQL中的数据类型时学到的有趣(有时令人惊讶)的事情。NUMERIC、INTEGER、DATE和char/varchar等数据类型存在于所有其他关系数据库系统中,因为使用此类数据的需求几乎是既定的。不同系统的实现可能略有不同,但通常有一些标准方法可以处理和分析这些类型的数据(例如,执行数学计算、找出字符串的长度、从一种类型转换为另一种类型等)。

在Postgres中,我们还有一些即使是经验丰富的开发人员也不太熟悉的数据类型。让我们快速了解一下数组、枚举和范围类型。

数组可能比较熟悉,但如果您是编程新手,请注意:它是一种用于保存对象集合的数据类型。在某些语言(如JavaScript)中,数组本身不必保存相同数据类型的值。然而,在Postgres中,数组元素必须都是同一类型-表定义暗示了这一点:

正如我们在上面的Countries列中看到的,数组声明必须具有该数组将包含的值的类型名称。

我在互联网上的搜索似乎表明,数组类型非常适合不需要严格遵循规范化规则的数据。以上面的示例为例(改编自“PostgreSQL故障排除”一书中的一个示例):COUNTRIES_VISTED表存储每个人去过的国家的列表。如果您想标准化数据,则可以使用一个表来存储人员和每个访问过的国家/地区的组合,结果是每个人最多有几十行。您还可以使用单独的查阅表格将两个字母的国家/地区代码链接到完整的国家/地区名称。

但是,您可能不一定需要维护查找表(有人可能会争辩说,更改国家名称并不一定要在访问过的国家列表中进行相应的更改)。您可能还会发现,将访问过的国家/地区列表保存在每人一条记录中会更有帮助,而不是每人可能需要处理数十条记录。使用数组意味着您可以去掉多余的表,并且不需要拥有属于同一个人的多行。

我遇到的其他几个可以使用数组类型的示例有:时间序列数据(如股票价格)、标记(用于分类或社交媒体)、从仪器获取的读数或测量。另一个好的经验法则可能是,如果您的应用程序代码中有使用数组的地方,并且您经常发现自己在获取整个数据集,则将数据存储为数组类型可以为您节省对查找表的多一次连接。

我喜欢这样可视化枚举:如果我只需要用下拉列表中的值填充一列,那么该下拉列表中会有什么呢?枚举类型自带一组可接受的值。(出于好奇:枚举类型在名为pg_enum的系统目录中注册,其中枚举值在内部表示为整数,每个枚举“标签”或名称存储为字符串。)。

你们中的一些人可能会想:“但这听起来不像是一个检查约束吗?或者可能是引用查找表的外键?“。你没有偏离正轨!这三种方法的实现方式不同,因此其中一种方法可能比其他方法更适合特定的用例。例如,如果我的可接受值列表将不断更改,我会选择查找表,因为修改表通常比修改枚举或约束更容易。所以,归根结底,这取决于您的特定需求,尽管我确实感觉到,将这三种方法视为解决问题的多个潜在工具是可以接受的。

您可能会说,“范围”可以描述某一组值,即当某物“在某个范围内”时,它就是该集合的一部分。因此,从表面上看,它听起来可能与枚举相距不远。我发现把范围类型的主要特征想成如下是有帮助的:

a)你一想到一个区间就会想到它的界限(即下限和上限)。b)范围内的值具有固有的顺序。

从技术上讲,您可以指定一个不存在限制的范围类型(因此范围是无限的),但是即使是一个无界范围也仍然有一个顺序。

范围类型适用于诸如年龄、价格和重量等数字数据;日期/时间数据也是典型的候选类型。我推荐阅读Jonathan Katz的博客文章,他在其中深入研究了如何将日期范围类型用于日程安排应用程序。

这些只是PostgreSQL中您可能没有使用过或没有意识到的几种数据类型。这些更“高级”的数据类型的酷之处在于,它们可以帮助简化您的应用程序代码,并让您编写更简洁的数据库查询。

例如,有一些内置运算符可以与范围类型一起使用,使您可以轻松地找到两个范围的交集,或确定某个值是否在该范围内。这并不是说,如果您设置了两个单独的列来表示范围限制(一个常见的列是开始时间和结束时间),您就不能得到相同的答案。但是,结合使用范围运算符和专门的索引(如GIST)可能有助于以更快、更高效的方式获得所需内容。

我们在Crunchy数据交互学习门户中关于数据类型的第二门课程重点介绍上述三种类型以及XML。它允许您使用一些示例数据来处理这些数据类型,并且还向您介绍了这些数据类型附带的一些有用的函数和运算符。

您是否曾经不得不更改您的数据结构并将其从常见的数据类型迁移到更高级的数据类型(如上述三种类型)?你的决策过程是怎样的?你的经历如何?请在下面发表评论。