存储过程的优缺点及使用场景
a、不可移植性,每种数据库的内部编程语法都不太相同,当你的系统需要兼容多种数据库时最好不要用存储过程。
当你的系统需要考虑适应各种数据库的,存储过程会是一个很大的瓶颈,比如SQLSERVER,ORACLE,MYSQL,DB2等等,每种数据库存储过程的语法不同,MYSQL早期流行版本甚至不支持存储过程,所以要实现存储过程的业务逻辑可移植性很难,如果性能不是指数级的增加都不应该考虑用存储过程。要能深入掌握各种数据存储过程,公司需要具备相应的人才。因此各种数据库存储过程的开发调试成本、测试成本,维护成本远大于这点性能提高带来的收益。采用常用标准语法或者采用HSQL之类的作法,逻辑放在应用程序里移植性会好很多。
如果你的数据库是固定的,那可以忽略这点,如很多定制型信息化系统数据库平台都是固定的。
b、学习成本高,DBA一般都擅长写存储过程,但并不是每个程序员都能写好存储过程,除非你的团队有较多的开发人员熟悉写存储过程,否则后期系统维护会产生问题。
这里说的学习成本高是一种相对开发人员的说法,一般程序员在学校里更多掌握的是常用开发语言,很少有人掌握PL/SQL,所以当你大量采用存储过程时,招来的人都需要培训PL/SQL。
我以前的一个团队有6个人,4个人都熟悉PL/SQL,C/S应用,因此很多业务逻辑都采用了存储过程,开发速度也不错,但后来换成B/S架构,系统也更复杂了,有20个人都不会PL/SQL,在一次系统重构时将一些业务逻辑的存储过程全换了,因为这些逻辑性能不是问题,取消存储过程后让普通程序员调试更简单,代码管理也更简单。
存储过程的语法、事务控制、调试方法这些与普通开发语言不同,当大量程序员不熟悉存储过程时架构师也不愿意把原本简单的架构搞得更复杂。
c、业务逻辑多处存在,采用存储过程后也就意味着你的系统有一些业务逻辑不是在应用程序里处理,这种架构会增加一些系统维护和调试成本。
业务逻辑集中管理会更易于维护与调试,你很难做到业务逻辑都放在存储过程里,比如关于一些客户输入数当据的简单校验,会话数据的校验,应用服务器缓存数据的校验。
d、存储过程和常用应用程序语言不一样,它支持的函数及语法有可能不能满足需求,有些逻辑就只能通过应用程序处理。
这个不太想举例,因为环境不一样,每系统的需求也不一样,如AES高级加密算法,也许这些在应用程序中已经有好的实现,那就不需要在存储过程中再搞一个了。
e、如果存储过程中有复杂运算的话,会增加一些数据库服务端的处理成本,对于集中式数据库可能会导致系统可扩展性问题。
select sum(object_id) c1 from all_objects;
select sum(power(object_id, 1.1)) c1 from all_objects;
可以试试这两条SQL的性能。power带小数的运算性能不好,如果在数据库中有大量这样的运算,CPU很容易成为瓶颈,而应用服务器可以更好的扩展,而且更善于做CPU运算的优化,所以这类会让CPU成为瓶颈的运算不宜放在数据库端处理。当然,这种需求不常见。
f、为了提高性能,数据库会把存储过程代码编译成中间运行代码(类似于java的class文件),所以更像静态语言。当存储过程引用的对像(表、视图等等)结构改变后,存储过程需要重新编译才能生效,在24*7高并发应用场景,一般都是在线变更结构的,所以在变更的瞬间要同时编译存储过程,这可能会导致数据库瞬间压力上升引起故障(Oracle数据库就存在这样的问题)。
这个问题只是针对高并发应用的系统,如果你的系统并发很低,每秒只有几次或几十次调用,可以完全不用考虑这个问题。
个人观点:普通业务逻辑尽量不要使用存储过程,定时性的ETL任务或报表统计函数可以根据团队资源情况采用存储过程处理。存储过程可以快速解决问题,但是移植性、维护性、扩展性不好,它有时会约束软件的架构,约速程序员的思维,在你的系统没有性能问题时不建议用存储过程。如果你要完成的功能只是一次或有限次的工作,如数据订正、数据迁移等等,存储过程也可以拿上用场。
如果你的系统很小,并且有50%的开发人员熟练掌握PL/SQL,人员结构稳定,那存储过程可以减少很多代码量,并且性能不错。当系统变复杂了,开发人员多了,存储过程的弊端就会呈现,这时你需要痛下决心了。