[pgrx开发postgresql数据库扩展]附1.存储过程的优缺点与数据库扩展函数

news2024/10/5 18:25:06

俗话说:天下大势,分久必合,合久必分。

最早的软件系统开发,讲究的就是一个全栈——在最早期的桌面软件时代,数据、用户界面和业务逻辑是完全混在一起的,讲究的就是一个一体化……那个年代也诞生了大量的码农界的传奇人物,比如:

后面嘛,开始讲究专业化,所以把数据和业务逻辑分开了,还搞了一个专门的名称,叫做CS架构:

好吧,上面那个不算,下面这个才是:

主要就是把数据和业务逻辑分离了,服务器专门管数据的存储(以及有限的部分对数据依赖度比较高的计算),而在客户端上复杂业务逻辑。

之后,又进化出来了BS架构与MVC模式:

包括CS架构,也在在借鉴BS架构的MVC模式下,也进化出了QML这一类的专门的做桌面APP界面的描述性脚本语言,基本上完成了UI与业务逻辑的分离。

后面更是进化出了微服务这种能分多细分多细的架构……

至于后面还要分细碎,我就不好预测,不过近些年来,有出现了一阵反潮流,什么概念呢?

叫做:

code push down:直接翻译过来就是代码下沉,下沉到哪里呢?就是下沉到数据库层面。(这个概念最早来自SPA的HANA数据库架构提出来的)

通俗来说,就是一句话:

在最贴近数据的地方做运算。

为什么说是复古风,因为最早的代码下沉,不就是存储过程么……下面我们就存储过程来聊聊今天的内容:

先说为什么在互联网时代,存储过程失宠了:

这是福报厂的Java开发手册:

很明确的规定不能使用存储过程,一般来说,理由如下:

首先是存储过程本身的缺点,主要有以下六个:

缺点

1. 兼容性和移植性差

如果你的业务逻辑复杂到需要写存储过程的地步,总会不可避免地用到数据库独有的特性和语法,不同虽然SQL有标准,但是不同数据库之间的PLSQL都是有一些不同地地方:

例如:

  • Oracle的叫做PL/SQL
  • SQL Server叫做T_SQL
  • postgresql叫做PL/pgSQL
  • DB2叫做inceptor-plsql……

(看到这里我已经有点晕了) 虽然他们都遵循SQL 99标准,但是别说不通库,就算同库不同版本之间,也有一些特性是不相同的。

所以,一旦发生了需要更换数据库时,这部分代码基本上就得需要重写。

如果只是简单地替换函数名和参数规则(如日期转换等),那成本还不高;如果用到了新数据库不支持的某种特性,那还要重新设计算法来编写计算逻辑;如果还要再兼顾性能因素,那成本就非常感人了。

反之,如果用高级语言来处理这些业务逻辑,对于数据库的依赖就降到最低了,特别是类似与ORM一类的技术,让数据库底层与业务逻辑几乎完全隔离,换了数据库之后,只需要换个连接字符串就行,其他代码几乎完全兼容。

2. 调试困难

所谓工欲善其事,必先利其器,对于码农来说,一个好的编辑调试工具是工作效率的前提。

而存储过程的开发一直缺少有效的 IDE 环境。(目前有明确具备调试能力的,只有Oracle的PLSQL DEVELOPER工具)。

构成存储过程的SQL本身经常很长,调试势必要把句子拆开分别独立执行,非常麻烦。即使是分步的运算,因为没有好的 IDE 支持,要看哪一步出错,也要把中间结果输出才行,仍然是非常麻烦。

存储过程的调试功能近年来略有起色,但离流畅实用始终差距甚远,数据库厂商似乎也无心解决。这点和Java、Python等高级语言拥有的成熟IDE(集成开发环境)的几乎完全不可同日而语。哪怕是备受诟病的C/C++在VIM下面开发,也有GDB这样的调试工具。而存储过程开发中这让码农们焦头烂额的调试自然会导致低下的开发效率。

3. 体系封闭

说到封闭性,其实是数据库本身的问题。数据库既然叫做“库”,那么外部数据只有入到库中才能计算和使用。

而现代应用数据源众多,先不说半结构化和非结构化这种东西,就算是标准的结构化数据,要临时转入到库中,其效率很低且开销也极大(因为数据库的 IO 成本高)。很可能跟不上访问需求,定时批量转入又很难获得最新的数据,同样影响计算结果的实时性。同时,很多ETL业务,往往有时间窗口(如当天夜里到第二天凌晨),赶上业务繁忙的时候还可能因为时间窗口不足无法完成 ETL工作而影响第二天的业务。

不仅如此,把外部数据存储在数据库中,又会形成众多中间表,面临中间表的各种问题。而且互联网上最通用的通常是多层的 json 或 XML 格式,在关系数据库中还要建立多个关联的表来存储,会进一步加剧中间表的问题,占用过多宝贵的数据库空间。

存储过程在数据库中运算自然继承了封闭性的特点,想混合计算外部数据很不方便。更别说如果还想在存储过程中,调用一下其他的API,来实现一些复杂的算法,更是几乎不可能完成的任务。

4. 耦合性高

高耦合是系统升级的噩梦,高耦合代表系统内各个部分高度的关联在一起,无法独立的维护和处理,这样出现任何问题都会造成牵一发动全身。

虽然从理论上来看,管用存储过程还是高级语言编写的后台逻辑功能,通常是为前台用户应用提供服务的,而用户只能理论上只能通过UI界面才能使用系统,所以这些东西本质上应该在一起,从而有机的组成完整的业务功能点。这就是早期所谓的一体化全栈模式。但哪怕这种模式下,也要尽量把各个部分做成独立的,以防止这种高耦合的产生。

但存储过程必然与数据库紧密耦合,所以实践中存储过程与前端应用是物理分离的,且无法使用统一的技术路线。对于同一个功能点的存储过程和前端应用,维护其中一处,通常就要维护另一处,但两者物理上分离,维护因此变得很困难,而不统一的技术路线则加剧了这种困难。

存储过程与数据库紧密耦合,反而与前端应用分离,这就容易使同一个存储过程被多个前端应用共享。时间一长,哪个存储过程到底被哪些应用调用就变成了谜团。如果某个应用的计算发生变化,面对谜团一般的共享调用关系,管理员只能新建存储过程而不敢修改原存储过程。这样恶性循环下去,存储过程越来越多,屎山也就越来越大,终将变得不可收拾。

5. 管理困难

在数据库中,存储过程的目录是扁平的,而不是软件工程或者文件系统那样的树形结构,要是脚本少的时候还好办,一旦多起来,整个系统就会陷入一团乱麻。

可以想象,多个项目的存储过程、同一个项目不同模块的存储过程、同一模块不同年份或不同版本的存储过程,这些如果混杂在同一个目录下,区分起来会非常困难,除非加大管理幅度,比如按项目、模块、年代、版本命名,这显然又会影响开发效率。有些项目管理较弱的团队,在开发周期紧张时,常常就顾不得这些规矩了,先赶着让项目上线再说,而上线之后这些遗留问题又容易被忘掉,结果常常一直存在很久。

最后导致的问题就是数据库中的存储过程会变成一个谁也不敢乱动的巨大屎山。

6. 开发、升级、维护困难

绝大部分的存储过程都是为查询分析服务的,但是这类业务的最大特点就是经常性会被前端需求所绑架,也就是需求一边,功能就得跟着改变。

由于存储过程与数据库紧密结合,所以这就带来了两个方面的问题:

  1. 存储过程编码的语法与实现依托于数据本身,不理解数据的情况下,对于存储过程的实现也几乎完全无法理解,这就给维护人员带来了额外的学习、理解和使用成本。
    存储过程的编写需要一定的专业技能。对于一些中小型公司来说,缺乏这方面的人才,开发难度比较大。而且从软件工程上来说,存储过程不利于代码版本控制和管理。存储过程通常集中在数据库中,也不易管理和维护。
  2. 代码的编译和发布的流程破坏了常规的安全规范。
    常见的项目安全规范就是程序员不应该具备数据库的管理权限,而数据库管理员一般不负责编译和部署。
    但是存储过程必须是发布在数据库上的,这样,要么程序员每次修改存储过程代码之后,提交给数据库管理员,由管理员编译并发布,但是这样会大大增加管理员的工作负担。
    要么给程序员赋予高级权限,至少也是创建存储过程的权限,这样就不用频繁打扰管理员了。而这么做虽然方便,但存在严重的安全隐患。
    本来做报表查询只需要对数据库有“select”权限就行,而可以编译存储过程的权限就太大了,几乎可以做一切。这时候程序员如果失误(不管是主观的还是客观的),很可能删除或修改了数据、甚至破坏整个数据库环境,造成严重的安全事故。

7. 加大了数据库系统的压力

在高并发的互联网场景下,并没有太多复杂的数据业务,反而对于常规简单数据服务要求很多,这样数据库就成为了一个系统里面压力最大的部分,在 常见高并发系统里面,数据库是最容易被攻破的环节,是因为相对于微服务架构下,天生就具备了容易横向扩展和负载均衡的应用系统而言,数据库的横向扩展的难度和成本都是指数级的,所以大部分高并发架构设计中,都使用了各种手段来保护数据库,例如Redis缓存、队列、读写分离等,希望把数据库的压力都分配出去。

而存储过程是直接运行在数据库上的,运算的任务是直接放在数据库引擎上的,这样就会使用一部分数据库的计算资源,加重了数据库的负担,这是与高并发架构设计思想是相悖的。

优点

任何一件事,既然客观存在,必然有他存在的理由,存储过程有这么多缺点,但是依然还活得好好的,所以必然有存在的理由,所以说完了问题,下面我们来说说存储过程的优点:

1. 高性能与事务性

存储过程可以将一组SQL语句封装在一起,作为一个单元来执行。这样可以减少数据库服务器与客户端之间的通信量,并且在最贴近数据的地方进行运算,最大限度的减少了各种IO开销。

在一些复杂业务逻辑中,存储过程可以将大量的复杂的业务逻辑封装起来,使得客户端代码更加简洁明了。

例如,在银行业务中进行转账时,可能需要检查账户余额、账户是否被冻结,同时还需要进行相应的日志记录等操作。如果将这些操作分散在多个客户端请求中完成,就会增加数据库服务器的负载,降低系统性能。而使用存储过程将所有的操作封装在一个单元中,可以显著提高系统性能。 另外它还提高SQL执行效率:存储过程可以预编译SQL语句,避免了每次执行SQL时都要重新解析的时间开销。

2. 安全性

存储过程的业务逻辑本身就是以SQL语句写成,所以常见的SQL注入这种安全问题基本上就直接可以避免了,另外通过存储过程,可以实现对数据访问权限的控制。例如,在银行行业中,只有具有特定权限的用户才能够进行某些敏感操作。

而这两项,也恰恰是银行业和金融业依旧在大范围的使用存储过程的主要原因。

随着互联网、云计算和大数据技术的兴起,存储过程开始逐渐失去它原有的优势。现在的互联网应用更加注重系统的可伸缩性和灵活性,银行业和金融业的新业务系统,也开始慢慢的放弃存储过程,转移到新的架构上来。

不过这些新的架构,是否能够完美支撑银行业,还有待时间的检验,要知道,互联网业务出了问题,杀码农祭天是个玩笑,但是银行业务出了问题,是真的有人要去坐牢的。

数据库扩展函数对于存储过程的改进

前面我们看到了存储过程的缺点,如果你是互联网派系的IT人员,可能会得出存储过程已经走向穷途末路的感觉,但是如果突然发现,世界上居然还有一种能够快速编写数据库扩展函数的能力,无疑是山穷水尽疑无路,柳暗花明又一村。

因为在(快捷、方便、有效的编写)扩展函数的加持下,存储过程很多的缺点都迎刃而解了。

例如我们就用Rust的PGRX框架来说吧:

  1. 兼容性和移植性这个问题,不同的数据库之间大概率还是无解,但是同一数据库的话,因为Rust的扩展函数讲究的是一个single-binary,既无依赖模式,这样就算不同数据库版本新增或者修改了什么特性,一般与扩展函数也无关。
  2. 调试困难这种事,在Rust这种高级语言下面,根本就不是个事,一大堆的IDE、工具、测试框架都在摩拳擦掌,饥渴难耐……
  3. 体系封版这种事情,Rust不但能够直接读写数据库本身,而且还能够直接读取外部数据、读取外部接口,所以这种事,基本上就是直接pass了。
  4. 耦合度高的问题,能够解决一部分,代码的逻辑可以通过library功能的方式,写在功能函数里面,可以独立维护与更新,但是最终到数据库里面,毕竟是贴在数据上面的,所以也无法全部解决。
  5. 管理困难这个问题,解决方式同4,代码逻辑可以按照正常软件工程的管理模式,但是数据函数部分,依然无法完全解决。
  6. 开发、升级、维护,同上,大部分问题在Rust开发中已经不是问题,但是与数据的问题依然存在。
  7. 此问题无解……

所以,我们发现,如果使用rust的pgrx一类框架来做数据库扩展,以求解决存储过程带来的问题,又回到了软件工程里面的经典论断,既:

没有银弹

不过,能解决60%以上的问题,我觉得就已经很不错了,真有可能是存储过程的续命良药也说不定。

打完收工。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL基础(三)基本的SELECT语句

1. SQL概述 1.1 SQL背景知识 1946 年,世界上第一台电脑诞生,如今,借由这台电脑发展起来的互联网已经自成江湖。在这几十年里,无数的技术、产业在这片江湖里沉浮,有的方兴未艾,有的已经几幕兴衰。但在这片浩…

同步辐射散射数据处理:从测量到分析的全流程解析

同步辐射散射数据处理:从测量到分析的全流程解析 同步辐射(Synchrotron radiation,SR)是指粒子在强磁场中受到加速或转向时所放出的辐射。这种辐射是一种非常强烈、具有非常高能量和亮度的电磁辐射。同步辐射散射(Sync…

怎么控制别人的电脑屏幕?

为什么需要控制别人的屏幕? 我们不可避免地会遇到一些情况,比如我们需要为我们的朋友、同事或家人提供有关 IT 相关问题的帮助,如果他们不知道它该怎么处理这些问题该怎么办呢? 这时,我们可能需要用我们的电脑…

聊点技术 | 全新功能,让Bonree ONE变得更强

4月21日,博睿数据ONE有引力2023春季产品发布会圆满落幕,Bonree ONE 2023春季正式版正式发布,带来更轻、更强、更智能的一体化智能可观测平台。 全新功能,让Bonree ONE变得更强 本文作者 产品经理高天明、产品经理吴学飞、产品经…

Mysql监控账号创建【Prometheus】

Mysql的监控采用一个使用mysqld_exporter启动多个进程来实现监控多个mysql实例。 代理部署架构如下 1,创建数据库监控账号 create user 监控账号mysqld_exporter主机的IP identified by 监控密码 with max_user_connections 10; 2,权限授予 grant pr…

KDSL-82-1000A大电流发生器

一、产品简介 KDSL-82-1000A大电流发生器(简称升流器),我公司自行研制开发的测试设备,它集国内外同类产品的优点于一身,采用数控技术,抗干扰能力强,和上一代升流器相比,由于采用低功…

NetSuite .id的用法

我们必须认清一个事实,NetSuite Saved Search是一个被封装化的SQL查询工具。在NetSuite的早期版本中,可以利用Formula字段做很多SQL语句上的灰色应用。但是慢慢的,灰色应用范围被压缩了。目前只剩下一个“.id”的应用了。 今朝我们就谈谈.id…

网络管理员优化提高网络性能需要关注的三个指标

网络管理员有一个主要责任:确保其网络的正常运行时间,同时不影响网络性能。然而,随着现代可部署解决方案通过传统的网络架构,这说起来容易做起来难。尽管现代解决方案在效率方面绝对比传统解决方案更上一层楼,但它们也…

任务态相关的一些知识总结

静息态的数据处理现在都比较简单了,因为有了fmriprep和qsiprep流程工具,没有特别的难度。 而关于任务态,则有一些独特的处理方式,因为最近要做任务态的数据分析,所以学习一下。 先学习下R的4个重输出函数:…

更懂业务的数智平台,应对数智化转型的“千变万化”

本文作者 跨界的申斯基 毫无疑问,随着数智化转型的加速,越来越多的企业正在把数智化战略提升到一个全新的高度,转型的进程也正从“浅层次”的数智化走向“深层次”数智化的阶段。 这也让企业的数智化转型进入到了一个全新的阶段,…

windows权限维持之shift后门

原理:沾滞键的目的是为了帮助那些按键有困难的人设计的,在Windows系统下连续按5次shift键后,系统就会执行C:\Windows\System32下的sethc.exe,也就是启用了沾滞键,但是当我们将shell.exe文件把sethc.exe文件通过更改名称…

AI 工具合辑盘点(七)持续更新 之 AI 音乐制作工具

AI 音乐制作工具 AI 也正在民主化音乐。它正在改变音乐创作的方式,赋予每个人成为音乐家的机会。创作音乐杰作所需的一切只是一个想法、一台电脑和一个 AI 音乐生成器。🎶 AI 生成的音乐可以在几分钟内创作出来,结果取决于你的提示——几乎…

Python-web开发学习笔记(1)--- HTML基础

大家好,我是尚拙谨言,欢迎来到本专栏。本专栏主要是为web开发学习服务的,一共分为3个部分:前端介绍、数据库、Django,均为python web开发的学习笔记,希望能帮助到大家,也以此作为我个人的学习记…

Qt 从入门到入土【下篇】

Qt 从入门到入土【上篇】 推荐一个非常好的视频 本文目录 6. 对话框QDialog6.1 基本概念6.2 标准对话框6.3 自定义消息框6.4 消息对话框6.5 标准文件对话框 7. 布局管理器7.1 系统提供的布局控件7.2 利用widget做布局 8. 常用控件8.1 QLabel 控件使用8.2 QLineEdit8.3 其他控件…

从不同视角来看待API数据接口

一、作为产品经理向客户推广API数据接口,需要注意以下几点: 1.了解目标客户:在推广API数据接口之前,首先需要了解目标客户的需求和痛点,针对客户的实际情况提供更具体化的解决方案。 2.强调API接口的价值&#xff1a…

Istio 故障注入之延时(fixedDelay)、中断(abort)

Istio 故障注入 Istio 故障注入与其他在网络层引入错误(例如延迟数据包或者直接杀死 Pod)的机制不同,Istio 允许在应用程序层注入故障。这使得可以注入更多相关的故障,比如 HTTP 错误代码等。 Istio 可以注入两种类型的故障&…

springboot整合vue2-uploader文件分片上传、秒传、断点续传

1:vue-simple-uploader介绍 vue-simple-uploader是基于 simple-uploader.js 封装的vue上传插件。它的优点包括且不限于以下几种: 支持文件、多文件、文件夹上传;支持拖拽文件、文件夹上传可暂停、继续上传错误处理支持“秒传”,…

2023年博客之星入围选拔重装开启——今年没有拉票环节啦

2023年博客之星入围选拔开始啦! 2022的博客之星大赛言犹在耳,2023的活动又接踵而至了。今年的博客之星(包括博客新星)的入围规则很简单: 2023年新规则 1.不需要拉票!不喜欢这个环节的有福啦 2.从年初就…

python对医疗数据进行分析,看看哪个年龄段最容易生病

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 什么是数据分析 明确目的–获得数据(爬虫,现有,公开的数据)–数据预处理——数据可视化——结论 准备 环境使用: 在开始写我们的代码之前,我们要准备好运行代码的程序 Anacon…

附录3-动态组件 component与keep-alive setup()写法

目录 1 基本使用 2 按钮切换组件 3 keep-alive 3.1 在切换组件的时候,默认情况下被切换的组件就会被销毁 3.1.1 数据情况 3.1.2 生命周期函数情况 3.2 使用 keep-alive 3.3 keep-alive的生命周期函数 3.4 缓存指定组件 include 3.5 不缓存指定组…