存储过程的优劣 好与坏-

 

        当你在开发一个基于数据库的应用的时候,你可能会想这样一个问题:数据库有关的事务操作部分因该放在那里?是以存储过程(stored procedure)的形式放在数据库端呢,还是将查询以及相应运算嵌在应用程序当中呢?要回答这样一个问题,你首先要了解存储过程以及内嵌SQL这两种 方案各自的优缺点以及他们分别适用的场合。

这也是我最近遇到的问 题,在写一个有大量数据库操作的程序,是在InterBase上开发;工作中又要不断在SQL Server和Oracle两种环境下操作,SQL Query Analyzer中用F5执行查询,PL/SQLDeveloper中用F8执行查询,这两个快捷键已经有些让我不知所措了。加上一大堆含义相同名称迥异 的概念,各自扩展的SQL语句,还有不同时期不同人写就的View,Stored Procedures,真是有些云里雾里的感觉。

我一直坚持只用标准的SQL语句编程,从效率、安全和维护方面出发也考虑利用存储过程来处理大量的数据操作,但可移植性方面的问题又让我望而却步。所以至今还是把大量的SQL语句嵌入到程序中,这其中利与弊又要如何考量呢???

为什么要使用存储过程(Stored Procedures)?

存 储过程是一组T-SQL语句,它们存放在一起形成一段SQL程序。在运行的时候,你可以传入一些参数;你得到的可以是结果集合(result set),也可以是输出参数(outputparameters),甚至是返回值(return value)。存储过程在第一次被执行的时候,数据库系统要首先对它进行分析和编译。编译后得到了一个执行计划(executionplan)。所谓执行 计划就是数据库具体执行这个存储过程的先后步骤的过程纪录。这个编译得到的执行计划被放置到数据库的缓存池中以备以后再次使用。如果这个存储过程今后再次 被调用,那么数据库将从缓存池中取出这个执行计划来运行。这样就避免了重复对该存储过程进行再次分析和编译,从而提高了数据库的性能。(这些缓存池中的执 行计划将一直被保存着,直到数据库重新启动或是系统内存不够用而被清除出缓存池)。

是否使用存储过程,我们可以从以下三个方面来进行分析。

一.性能(Performance)

在 网络传输方面,存储过程比查询仍然占有优势。因为使用存储过程只需要向数据库传递存储过程的名字和必要的参数,而不是像查询那样要传输全部查询语句。如果 查询逻辑复杂的话,那么查询语句的大小也将会比较可观。另外,设计合理的存储过程可以减少客户端和数据库端之间的往返,甚至减少到一次。在决定是否使用存 储过程的时候,你还要判断你的特定操作是不是利用了存储过程的长处。总体来说:

  • 基于集合的运算(Set-Based)是SQL的强项
  • 基于行的运算(Row-Based)以及基于字符串的运算(String manipulation)不是SQL的强项。

二.可维护性和抽象能力(Maintainability and Abstraction)

使 用存储过程另外一个潜在的好处就是可维护性好。对于好多更动,你也许只需要更改存储过程的具体实现就可以完成。所有使用它的客户端程序就不需要重新修改, 调试和编译。这样很多变动对于客户程序来说就是透明的(transparent)。在大多情况下,这种办法往往是最有效和最简单的。

通过抽象具体实现(implementation)和将SQL语句放在存储过程中,可以使任何客户端调用者以一个统一的形式来访问数据。不同的用户也将永远得到同一样的结果。

需要指出的一点是使用存储过程不能防止你修改数据库结构和事务处理规则。如果更动比较大,需要重新设计传入的参数或者返回值,那么你将需要修改客户端调用这些存储过程的程序段。

你 应该考虑到使用存储过程来封装你的事务处理逻辑将影响应用的可移植性。存储过程是和SQL数据库捆绑在一起的,如果你想更换数据库平台,你可能要重写这些 存储过程。如果可移植性对你的应用的是非常关键的,那么将事务处理逻辑放在数据库系统中立(RDBMS-neutral)的中间层(middle -tier)比较好。

三.安全性(Security)

从管理用户访问信息角度来讲,它可以通过让用户访问一定的存储过程来保证用户可以访问特定的数据,这是一种间接的数据访问,而不是直接对用户开放式据库表格。其实我们可以将存储过程假想为数据库系统的View。唯一的区别就是存储过程可以变更参数而使得结果动态变化。

存 储过程还可以让你在程序安全性方面有所改进。它可以防备一种叫做SQL注入式的攻击(SQL injection attacks)- 这种攻击主要是用AND或是OR运算符将命令拼接在有效的输入参数之后。存储过程还可以隐藏事务处理规则于数据库端,而不是放在客户程序端。在有些情况下 (比如涉及到知识产权等等),这种隐藏是非常重要的。

存储过程适用于你吗?

综上所述,使用存储过程有如下几个突出优点:

  • 提高新能,减少了网络流量
  • 在数据库端一点的维护(single point of maintenance )
  • 抽象和概化业务逻辑,增强了一致性和安全性
  • 减少了一些可能的恶意攻击的机会
  • 鼓励执行计划的重用性(Encourage execution plan re-use )

如 果你的应用程序能有效的利用存储过程的上述优点,那么你就应该尽量使用。但是如果你的应用要求有很高的可移植性,或者数据库的结构变动很大,不能相对稳定 下来,那么你可能要试一试其他方法了。比如你现在在SQL数据库上为用户开发一个早期可行性验证程序,今后用户很可能使用MySQL或是Oracle等其 它数据库,那么你就因该避免使用SQL数据库的存储过程,而使用程序内嵌的数据库操作语句。这样当你更换数据库平台的时候,可以极大的保证程序不受影响。

另 外,你还要考虑使用存储过程的技术问题。也许你和你的手下非常不熟悉存储过程编程,并且没有时间去很快掌握它。这些因素你也需要通盘考虑。另外如前所述, 数据库存储过程擅长于基于集合(set-based)的操作,而不擅长基于行(row-based)的操作。如果你对存储过程没有很好的了解,而不正确的 使用了它往往会导致很不好的执行性能。所以如果你决定使用存储过程,那么多花一些时间来学习它是很有必要的。

并 且,编写复杂的存储过程可读性不如高级语言程序,调试环境也远远不如成熟的编程工具强大。由于各个厂商都对标准的SQL语句进行了不同扩展,所以移植存储 过程要负出很大代价。要求编程人员对每种数据库系统都有很深入的理解也是不太现实的。通过开发支持客户端的自动升级是比较简单的,但要升级服务器端的存储 过程,却不见得轻而易举。

由于将业务逻辑都集中到服务器端处理,系统对服务器的要求几近苛刻,而编写和维护高效可读的存储过程,将是一个异常艰难的挑战;而在另一端,高级编程语言不断发展,硬件条件不断提高,网络环境也不再成为主要瓶颈,而这些资源却被无端浪费.

是不是要将所有处理都交给服务器,这实在是个问题?

个人建议:为了更好的移植,最好不要用存储过程、触发器和视图等……

This entry was posted in database and tagged . Bookmark the permalink.

Leave a comment