我可以通过Postgres做所有事情:Elixir程序员的经验教训

2020-11-30 03:02:33

如果您甚至对圣经一无所知,您可能会认识到腓利比书4:13所说的嘲讽标题。尽管我之所以选择它是因为我认为它很吸引人,但也可以说许多开发人员对某些数据库有宗教信仰。

这篇文章的目的是阐明关于发展问题的另一种思考方式。如您所见,这些问题都可以通过Elixir代码解决。我想给出一些具体的问题示例,这些问题可以通过数据库更好地解决。

Postgres有一些问题只能解决。自从20多年前推出以来,许多工作都在增加功能和性能上。

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

所有示例均假设您使用的是Ecto,但是这些概念可以轻松地移植到其他系统上。将逻辑移入Postgres并不意味着放弃您的ORM。幸运的是,通过结合迁移和片段,我们可以少量地注入SQL以实现我们的目标。

在此示例中,架构表示汽车。一共有3列:engine_type,mpg和kwh。汽车永远不应在所有3个字段中都有数据。仅带电动机的汽车应具有kwh。并且只有汽油发动机应该具有mpg。

假设您要确保在变更集中验证了逻辑,则可以这样创建一个自定义验证器:

使用postgres,迁移会获得新的检查约束。支持此约束只需要向变更集添加一个check_constraint / 3函数。采用这种策略,数据库将确保遵循业务逻辑,并且变更集将返回有用的错误(如果没有)。

此外,还将验证数据库中的所有数据。即使它没有通过变更集(也许您是从外部来源导入的数据),我也认为采用皮带悬挂式方法通过在前端和后端进行验证来验证数据是很常见的。结束。在db级别添加这种类型的验证的是腰带和悬吊带以及弹性废料带。

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

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

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

假设您的用户根据价格搜索汽车。您想向他们展示价格恰好是他们想要的汽车,但也要向他们展示一些价格越来越少的汽车。在长生不老药中,这可能意味着获取3个结果列表并将其合并。

Postgres已经在按顺序存储数据。使用窗口函数lag和Lead,您可以让postgres定位完全匹配的对象,然后仅在索引中获取其周围的行。认为这就像去一辆车,那里每辆车都按价格顺序停放。如果您以5,000美元的汽车开始,那么价格接近的汽车将停在其旁边。

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

CTE是一个临时结果集,您可以在另一个SQL语句(包括SELECT,INSERT,UPDATE或DELETE)中进行引用。每当您有递归查询时,它都会很有用。

在fuzzy剂中搜索模糊匹配可能效率很低。假设您要进行文字搜索,以同时查看汽车的品牌和型号。此外,如果用户拼错名称,则要返回匹配项。

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

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

我刚刚介绍了postgres功能的表面。希望我给您一些有关如何利用已经安装的功能非常强大的工具的想法。

在组织,查询和转换数据时,Postgres具有很多优势(这就是它的设计目的。)在您的应用程序中肯定有一个将逻辑留在时间和地点的方法,但是我希望您至少考虑一下如何移动逻辑进入postgres可以为您提供帮助。

我遗漏的一些功能包括视图,触发器和pg_notify。如果您有兴趣,请查看有关缓存不老长寿应用程序的本文。