当前位置: 首页 > 科技观察

据说阿里禁止使用存储过程?

时间:2023-03-20 21:30:57 科技观察

先说优点吧。毕竟用的人还是很多的,肯定是有一些优势的。很少有人提及存储过程在SQL过程化中的优势,这似乎是理所当然的。SQL的语法要求数据处理必须用一句话来写,无论嵌套多少层,使用多少子查询,这对于复杂的数据处理来说简直就是一场灾难。存储过程让SQL支持分步计算。虽然是多条独立的SQL语句的拼接,虽然可能需要经常写临时表,虽然……,至少这个过程解决了很多人的数据处理困难。不过,过程化计算并不是存储过程的专利,用Java命令SQL也是可以的。光是这个优点还不足以让程序员偏爱存储过程。接口与逻辑分离接口与逻辑分离是现代应用程序开发的基本原则。相对于后台数据处理逻辑,接口会有更多样的环境,如PC、手机等,业务稳定性不强,经常变化。如果能将两者分开,开发维护接口不需要和数据处理逻辑一起改变,成本也会低很多。使用存储过程可以实现接口和逻辑的分离。存储过程运行在后台数据库中,只要向前端提供数据即可,无需关心界面的形式和变化。将所有的数据处理逻辑写成存储过程,也有利于统一数据的出入口,易于实现数据的权限控制。再次“但是”,接口和逻辑的分离并不是存储过程的专利。只要做一个数据访问层,所有进出的数据都会经过这个访问层,达到同样的效果。事实上,一些应用程序确实这样做了,但在微服务流行之前并不常见。之所以这样,是因为从开发复杂度上来说,结构化数据写SQL要比写Java容易的多。但是,微服务架构强加了Java中数据处理逻辑的机制,实际上牺牲了开发效率。性能好一般使用存储过程会比使用Java直接SQL在库外完成数据处理有更好的性能。这样做的主要原因是数据没有出库。外部程序访问库中的数据时,必须使用数据库提供的接口,而这些接口的性能大多较差,尤其是Java程序的JDBC接口。每次下SQL让数据库执行,都会调用这个接口,速度不会增加。如果应用程序和数据库不在同一台物理机上,会有一定的网络延迟,但相对于接口的低性能来说并不严重。在外部计算时,从数据库中获取数据的时间往往超过计算自身的时间。存储过程的良好性能主要归功于数据库的低效访问接口。综上所述。存储过程的优势主要来自两个方面:一是SQL的数据处理能力。至少现在,在结构化数据处理,尤其是复杂计算方面,SQL还是比Java强很多。二是图书馆计算方便。不需要数据出库所节省的IO成本对于数据密集型任务有很大的优势。说说缺点吧。据说阿里有个军规,“禁止使用存储过程。存储过程难以调试和扩展,而且不可移植。”让我们列出存储过程的缺点。便携性差。存储过程的移植确实非常困难。一般业务逻辑比较复杂,需要写存储过程。必然会用到数据库特有的特性和语法。更换数据库时,需要重写这部分代码。如果只是简单的替换函数名和参数规则(比如日期转换等),成本并不高;如果使用新数据库不支持的特性,需要重新设计算法来编写计算逻辑;性能因素,有时会成为不可能完成的任务。调试难编辑调试是个大问题,存储过程的开发一直缺乏有效的IDE环境。SQL本身往往很长,在调试模式下将语句拆开单独执行非常麻烦。存储过程中经常会出现很多长SQL,当然也是同样的问题。即使是一步一步的计算,因为没有很好的IDE支持,要靠哪一步出错来输出中间结果,还是很麻烦的。存储过程的调试功能这几年略有改进,但远谈不上流畅和实用,数据库厂商似乎也无意解决。这与Java等成熟的开发环境完全不同。调试困难,自然会导致开发效率低下。系统关闭说到关闭,其实是数据库的问题。数据库有“库”的概念,外部数据只有存入数据库才能计算。但是现代应用中数据源多,临时传输效率很低(因为数据库IO成本高),可能跟不上访问需求。调度批量传输时,很难获取到最新的数据,也会影响计算结果的实时性。.同时,ETL往往有一个时间窗口(比如从当天晚上到第二天凌晨),当业务繁忙时,ETL工作可能会因为时间窗口不足而无法完成,会影响第二天的业务。不仅如此,在数据库中存储外部数据会形成很多中间表,中间表会面临各种问题。而且从网上抓取的一些数据往往是多层的json或者XML格式,必须在关系数据库中建立多个关联表进行存储,这会进一步加剧中间表的问题,占用太多宝贵的数据库空间。存储过程在数据库中的操作自然继承了闭包的特性,与外部数据混合计算非常不方便。耦合度高的存储过程通常服务于前端应用程序。理论上,两者应该一起构成一个完整的业务功能点。但是存储过程与数据库耦合度很高,所以实际上存储过程与前端应用在物理上是分离的,无法采用统一的技术路线。对于同一个功能点的存储过程和前端应用,维护其中一个通常需要维护另一个,但两者在物理上是分离的,因此维护变得非常困难,不统一的技术路线加剧了这个问题。困难。存储过程与数据库紧密耦合,但与前端应用程序分离,这使得同一个存储过程很容易被多个前端应用程序共享。久而久之,哪个应用程序调用了哪个存储过程就成了一个谜。如果一个应用的计算发生变化,面对神秘的共享调用关系,管理员只能新建一个存储过程而不敢修改原来的存储过程。如此恶性循环下去,存储过程会越来越多,谜底会越来越大,最终会变得不可控。困难存储过程的目录是扁平的,而不是像文件系统那样的树状结构。脚本少的时候还好办,一旦多了目录就乱了。可以想象,如果多个项目的存储过程、同一个项目不同模块的存储过程、同一个模块不同年份或版本的存储过程混在同一个目录下,将很难区分除非增加管理,比如按项目、模块、年份、版本命名,这明显影响开发效率。一些项目管理薄弱的团队,往往在开发周期紧迫的情况下,无视这些规则,抢先把项目上线。推出后,这些遗留问题很容易被遗忘,结果往往会持续很长时间。安全性差很多存储过程是为了查询分析,这类业务的需求是经常变化的。由于存储过程与数据库紧密结合,程序员每次修改存储过程代码都必须提交给数据库管理员。编译发布管理员无疑会大大增加管理员的工作量。所以通常的做法是给程序员高级别的权限,至少是创建存储过程的权限,这样就不用经常麻烦管理员了。这很方便,但存在严重的安全隐患。本来做报表查询只需要对数据库有“读”权限,但是编译存储过程的权限太大了,几乎无所不能。如果程序员出错,很可能会删除或修改数据,造成严重的安全事故。开源SPL作为库外的存储过程。从列举的优缺点数量来看,缺点远远多于优点,所以不难理解阿里的军规:能不能用存储过程。当然,是否使用存储过程完全是根据自己的情况综合考虑的,比如饮用水的温度。事实上,存储过程并不是不可替代的。开源SPL可以解决存储过程的各种缺点,同时延续其优点,实现“库外存储过程”。集算器SPL是专业的开源数据计算引擎,提供独立于数据库的计算能力。数据库更换不需要更改SPL计算脚本,解决了存储过程的可移植性问题;简单易用的IDE环境,具有完备的编辑调试功能。算法的实现更简单;SPL系统更加开放,可以直接使用各种数据源进行计算;“外部存储过程”不依赖于数据库,可以和应用程序一起存储,解决耦合问题;利用文件系统的树形结构进一步解决管理问题;SPL独立的数据库操作不会引起安全问题。SPL在库外实现了存储过程,不再依赖数据库,解决了原来绑定数据库带来的各种问题。直观易用的开发环境相对于编辑调试存储过程的难度,SPL提供简单易用的开发环境,单步执行,设置断点,所见即所得的结果预览窗口,开发效率更高.库外计算减少了耦合并提高了可移植性和安全性。SPL提供不依赖于数据库的计算能力,在库外进行计算。原来必须依赖存储过程的两种能力(计算和步进)完全可以用SPL代替,实现“库外存储过程”。这样,原本紧耦合在数据库中的计算逻辑就可以完全独立于应用程序之外,从而降低与数据库的耦合度。与数据库解耦后,数据库的变化不需要修改SPL的计算逻辑,可以方便移植。同时,SPL实现的“库外存储过程”的创建和使用不需要对数据库的写权限,完全可以避免使用存储过程带来的安全问题。在运维方面,SPL是解释执行的,自然支持热切换。能够很好的适应微服务架构下多变的服务修改需求,应用修改即时生效,无需重启。数据处理逻辑位于SPL文件(.splx)中,修改后实时生效,相对Java等需要重启服务的编译型语言有很大优势。在管理方面,SPL文件采用文件系统管理机制。树形结构可以清楚地存储每个应用程序和每个模块的计算逻辑。在不知道正在使用哪些模块的情况下易于使用和管理。多源支持和开放系统不同于需要先存储数据然后计算的数据库。面对多样化的数据源,可直接计算SPL。数据存储不仅时效性差,而且不能保证数据的实时性。此外,不同的数据源各有优势。文件的IO效率很高,NoSQL可以存储文档数据,而RDB计算能力强,数据存储无法享受这些优势。SPL提供开放的数据源支持,几乎所有你听说过或没听说过的数据源都可以支持。您不仅可以连接和获取数据,还可以跨数据源执行混合计算。SPL可以充分利用各种数据源的优势后,更高效地实现跨源计算。在开放体制下,不再有“图书馆”的概念,充分利用各种数据源的特点,充分发挥其优势。简洁的代码支持流程,提高开发效率。存储过程虽然支持过程式计算,但是SQL本身很难实现复杂的计算。这是由SQL的特性决定的(缺乏离散性、集合不全等)。记录查询某只股票的最长连续上涨天数,SQL(oracle)写法如下:SUM(RisingFlag)OVER(PARTITIONBYcodeORDERBYday)NoRisingDaysFROM(SELECTcode,day,CASEWHENprice>LAG(price)OVER(PARTITIONBYcodeORDERBYday)THEN0ELSE1ENDRisingFlagFROMstock))GROUPBYNoRisingDays)GROUPBYcode你可以试着读一下这个SQL在做什么。是不是很绕?其实按照一步一步的解法,只需要3步就搞定了,没必要这么绕。存储过程是用SQL实现的,自然继承了这个缺点。我们经常在项目中看到几千行,几百KB的存储过程,因为SQL对复杂计算的支持不是很好。SPL不仅支持自然支持流程计算,数据处理可以分为多个步骤,按照自然思维一步步进行,还提供了丰富的计算类库和敏捷的语法,基于SPL,可以更轻松地实现复杂的计算。看一下前面代码的效果:【计算目的】找出占销售额一半的前n个客户(大客户)的订单情况。A1=file("/opt/ods/orders.csv").import@tc()2=A1.groups(客户;sum(金额):金额).sort(金额:-1)3=A2.sum(金额)/24=05=A2.pselect((A4=A4+金额,A4>=A3))6=A2.(客户).to(,A5)7=A1.select(A6.pos(A1.客户))循序渐进,先找到符合条件的大客户,再查询这些客户的详细订单信息。这些计算都是在库外完成的,甚至可以使用文件数据源。从实现过程来看,SPL的过程式计算优于存储过程,语法更简洁。上面说了某只股票最长连续上涨天数的计算,SPL的实现如下:A1=db.query("select*fromstockorderbyday")2=A1.group@i(price