我可以通过Postgres做所有的事情:给长生不老的程序员上的课

2020-06-04 07:24:27

如果你对“圣经”有一点粗略的了解,你可能会认得“腓立比书”第4章第13节中的那个半开玩笑的标题。虽然我选择它是因为我认为它朗朗上口,但公平地说,许多开发人员对某些数据库有着宗教上的亲和力。

这篇文章的目的是阐明另一种思考发展问题的方式。正如您将看到的,这些问题都可以用灵丹妙药代码来解决。我想给出一些用数据库更好地解决问题的具体例子。

Postgres只是更擅长解决一些问题。自20多年前推出以来,在添加功能和性能方面做了大量工作。

此外,我还看到了很多项目,其中应用程序CPU经常处于负载状态,而DB服务器CPU徘徊在5%左右。在所有条件相同的情况下,这些技术必须对跨资源重新分配负载有好处。

所有示例都假设您使用的是ECTO,但是这些概念可以很容易地移植到其他系统。将逻辑移入Postgres并不意味着抛弃您的ORM。值得庆幸的是,通过结合迁移和片段,我们可以少量地注入SQL来实现我们的目标。

在本例中,模式表示一辆汽车。共有3列:engine_type、mpg和kwh。一辆车不应该在所有3个字段中都有数据。只有装有电动马达的汽车才应该有千瓦时。而且只有汽油发动机才应该有每加仑油耗。

假设您想要确保在变更集中验证逻辑,您可以创建一个自定义验证器,如下所示:

使用Postgres,迁移将获得新的检查约束。支持此约束只需要向变更集添加一个check_straint/3函数。使用此策略,数据库将确保遵循业务逻辑,如果不遵循,变更集将返回有用的错误。

此外,还将验证数据库中的所有数据。即使它没有通过变更集(可能您从外部源导入了数据)。我认为,通过在前端和后端进行验证来采用一种简单的方法来验证数据是很常见的。在数据库级别添加这种类型的验证是腰带和吊带和弹性废纸带。

Citext是Postgres的延伸。它添加了一个本质上是不区分大小写的字符串的新数据类型。安装它非常简单(如下所示)。

在幕后,Postgres实际上将查询的两边都转换为小写。顺便说一句,这通常是您在应用程序代码中要做的事情,以实现相同的目的。

如您所见,执行不区分大小写的搜索所需的长生不老的代码稍微复杂一些。此外,如果您决定将其添加到现有数据库,则需要迁移所有现有数据。使用Citext没有这一要求。

假设您的用户根据价格搜索汽车。你要给他们看的车和他们要的价格完全一样,但也要给他们看一些多一点和少一点的车。在灵丹妙药中,这可能意味着获得3个结果列表并合并它们。

Postgres已经在按顺序存储数据。使用窗口函数LAG和LEAD,您可以让Postgres确定精确匹配的目标,然后在索引中抓取它周围的行。把这想成是去一个停车场,那里每辆车都是按价格顺序停放的。如果你从5000美元的车开始,价格接近的车就会停在它旁边。

在上面的示例中,您还可以看到CTE的用法。顶部(以“with”开头)定义查询中使用的CTE。

CTE是一个临时结果集,您可以在另一个SQL语句中引用它,包括SELECT、INSERT、UPDATE或DELETE。它在您进行递归查询的任何时候都很有用。

在灵丹妙药中,搜索模糊匹配的效率可能非常低。假设您想要一个文本搜索,既可以查看汽车的型号,也可以查看汽车的型号。此外,您还希望返回近匹配项,以防用户拼错名称。

在elxir中,您可能需要加载每辆车,然后迭代每辆车(两次)以计算字符串相似度并对结果进行排序。在本例中,我们使用字符串模块中提供的jaro_Distance。

通过将该逻辑移到数据库查询中,我们可以使用Postgres内置的函数。Postgres中提供了Levenshtein距离计算,无需任何插件。

我只是触及了Postgres功能的皮毛。我希望我已经给了您一些关于如何利用您已经安装的这个非常强大的工具的想法。

Postgres在组织、查询和转换数据方面有很多优势(这就是它设计的目的)。在应用程序中保留逻辑肯定是有时间和地点的,但我希望您至少能考虑一下将逻辑移入Postgres会对您有什么帮助。

我省略的一些特性包括视图、触发器和pg_NOTIFY。如果您对这些感兴趣,请查看这篇关于缓存长生不老药应用程序的文章。