存储过程的危害



在播客的聊天“锌PROD”,他们下降的一篇文章对一些人是如何传输的所有的业务逻辑的存储过程PL / pgSQL的。并且由于该文章具有许多优点,因此意味着有些人,甚至可能是大多数人,都对这种重构持积极的态度。



我不会在树上散布自己的想法,但会立即引发使用存储过程的诸多弊端。



存储过程的缺点



版本控制



如果就php代码而言,您可以简单地在git中切换到另一个分支并查看发生了什么,那么仍然需要将存储过程推入数据库。传统的迁移在这里无济于事:如果将所有更改作为新的CREATE或REPLACE PROPEREDURE写入存储,那么代码审查就会很麻烦:总会有一个新文件,不清楚要比较什么。因此,您将必须寻找其他工具或编写自行车。



pl / pgsql语言本身



它是90年代的过时的过程语言,根本没有发展。没有OOP或FP或其他任何内容。语法没有丝毫语法糖的提示。



例如,必须在过程的开始,在特殊的DECLARE块中声明变量。这是我们祖父所做的,在此对Pascal语言有一定的怀旧之情,但要感谢,而不是在2020年。



比较两个在php和pl / pgsql中执行相同功能的函数:



CREATE OR REPLACE FUNCTION sum(x int, y int)
    RETURNS int
    LANGUAGE plpgsql
AS $$
DECLARE
    result int;
BEGIN
    result := x + y;
    return result;
END;
$$;


function sum(int $x, int $y): int
{
    $result = $x + $y;
    return $result;
}


大约多涂2-3次。



另外,语言是解释性的,没有JIT等。(如果最新版本有任何更改,请纠正我)。那些。一切都非常缓慢和悲伤。如果您使用某种存储方式,则使用纯SQL或v8(即javascript)。



调试



相信我,调试php代码要简单100500倍。您只是更正了一些,然后观察结果。您可以在IDE中通过xdebug覆盖echo或查看其中的内容。



调试存储过程很不方便。这必须在pgadmin中完成(通过启用特殊扩展名)。为了方便起见,PgAdmin离PHPstorm很远。



记录和错误处理



忘掉美丽的json,跟踪从stdout落下,然后到Graylog和哨兵。这样,所有这些都会自动发生,如果控制器没有捕获到异常,则会给用户500错误。



在pl / pgsql存储中,您将手动执行所有操作:



GET DIAGNOSTICS stack = PG_CONTEXT;

RAISE NOTICE E'--- ---\n%', stack;



收集指标



您不能像golang中那样仅添加/ metrics端点,这将被Prometheus吸收,您可以在其中填充业务和其他度量指标以进行监视。我只是不知道如何使用pl / pgsql。



缩放比例



存储过程的执行浪费了数据库服务器上的资源(例如,CPU)。对于其他语言,可以将逻辑移至其他节点。



依存关系



在php中,您可以使用composer程序包管理器,一口气从Internet提取所需的库。就像在js中将是npm,在Rust中将是货物,等等。



在pl / pgsql世界中,人们不得不受苦。根本没有这种语言的依赖管理器。



构架



在现代世界中,Web应用程序通常不是从头开始编写的,而是在使用其组件的框架的基础上进行组装的。例如,在Laravel上,您可以立即使用路由,请求验证,模板引擎,身份验证/授权,适用于所有情况的100,500个助手等。以过时的语言从头开始手工编写所有内容-不用了,谢谢。



将有很多自行车,这些自行车将在以后进行维护。



单元测试



甚至很难想象在pl / pgsql存储区中组织单元测试有多么方便。我从未尝试过。请分享评论。



重构



尽管有一个用于处理数据库(Datagrip)的IDE,但是重构工具对于公共语言来说要丰富得多。各种短毛绒,简化代码的技巧等。



一个小例子:在我在本文开头给出的代码段中,PHPStorm暗示了变量是$result可选的,您可以执行此操作(return $x + $y;



对于plpgsql-沉默)。



存储过程的优点



  1. 沿后端DB路径驱动中间数据没有开销。
  2. 查询计划被缓存在存储过程中,这可以节省几毫秒。那些。作为查询的包装,有时会很有意义(在极少数情况下,不是在pl / pgsql上,而是在裸露的sql上),如果负载很高,并且查询本身可以快速执行。
  3. 当为postgres编写扩展名时,不能没有存储空间。
  4. 如果出于安全原因要隐藏某些数据,则仅允许应用程序访问一个或两个存储(罕见情况)。


结论



我认为,只有在非常少见的情况下,才可以确定完全没有存储过程才需要存储过程。在其他情况下,您只会使开发人员的工作复杂化,而且非常复杂。



我会理解,如果在原始文章中将某些逻辑转移到了SQL,这是可以理解的。但是为什么存储是一个谜。



如果您认为我错了,或者您知道与存储过程有关的其他情况(正反两方面),并在注释中写上,我将非常高兴。






All Articles