是否使用存储过程

 

存储过程的性能要比sql语句强很多吧!

存储过程性能比单纯的SQL要低的


淘宝就是一个存储过程没有,一个函数没有,一个触发器也没有

全部交给业务逻辑处理

使用大量存储过程会带来很多弊端

上次跟楼方鑫大师讨论时,就说到这个,存储过程的性能是不高的

---------------------------------------------------------------------

首先要告诉楼主的是,

存储过程的解析在Oracle里首先是由PL/SQL引擎来解析——然后再由SQL引擎来解析

比单纯的SQL解析肯定要慢的

---------------------------------------------------------------------
在Oracle中,存储过程就是PL/SQL的模块

PL/SQL引擎会执行过程化语句,但它把SQL语句传送给SQL引擎处理,然后SQL引擎把处理的结果返回给PL/SQL引擎。

PL/SQL和SQL引擎间的频繁切换会大大降低效率。
---------------------------------------------------------------------
将业务放到数据库中去实现  后期维护可能会存在很大的问题!
---------------------------------------------------------------------
全用存储过程可能会带来的问题比大部分用SQL带来的问题多。除非你们的团队存储过程和性能优化特别猛!~ 因为很多人熟悉SQL,但是不熟悉PLSQL,为什么放弃熟悉的而且很好的东西,去用不熟悉的东西呢?当然可能会用到存储过程的,但是绝对不是全部!~

---------------------------------------------------------------------
从应用分层的原则,大量使用存储过程导致业务逻辑分散在DB和应用服务器层,肯定不好开发维护和更新。
从性能来说,SP肯定不是最优的,我知道的案例就有某运营商原来计费批价都用SP,后来很难满足性能的问题。
总体来说,SP可以用,但要很慎重,最好只用来维护,不用于业务逻辑和支撑高并发高性能的东西。
---------------------------------------------------------------------

这个主要看你的应用。对于计算密集型的,可以用PL/SQL,对于操作密集型的(比如淘宝)能用SQL的就不要用PL/SQL。我想你的web网站也是操作密集型把,最好能用SQL的就不要用PL/SQL,把逻辑都写在应用中。
----------------------------------------------------
不相信我说的算了

淘宝中包括复杂的order by , sum这样的计算都是应用通过算法处理的,而不是数据库处理的

数据库只做合适的事情

关于存储过程,首先带来的问题就是业务变动,然后数据库扩展,业务扩展

你怎么弄,扩展十几个数据库时,你去把存储过程迁移十几次去?那不把你搞死

如果业务逻辑变化的时候,怎么弄,改存储过程只有

然后就是在并发比较高的OLTP,性能是很差的

还有对测试人员来说,调试时,你还要他专门跑到数据库里去调试存储过程?如果是SQL,他直接跟踪调试就可以了

----------------------------------------------------

space6212
版主

 #35使用道具  发表于 2010-6-29 15:42  
其实这是一个平衡点的问题,
1. 一般来说,一个DB server会对应着几台、几十台甚至更多的app server,这就带来一个问题,一个功能放在db做,可能需要额外的5%的CPU,放在app做,可能需要额外20%的CPU,表面上是应该放在db做,但是不要忘记,app是很多的,分摊到每一个app server可能只有1%的CPU了。而且不要忘记,app server是很容易扩展的,而db是不容易扩展的
2. 从人员配备来说,一般dba都是紧缺的资源,一个dba对付几十个开发是很常见的。如果让dba做这些事情,那需要多少dba?如果让app开发人员写PL/SQL,你觉得他能写得比程序更高效吗?

从我了解的情况下,越是大型的web应用,越把数据库用途简化:只是保存数据的一个容器而已。

----------------------------------------------------
同意, 虽然不了解淘宝也不了解百度。
不过在泡论坛的时候,看过有人写说ebay还是什么比较大的公司,把数据库压力减到最轻。
因为app服务器/web服务器是很容易扩展的, db服务器很不容易扩展。
把运行压力都放在app服务器上面。

我们现在公司给某运行商做的分析系统,接口的是另外一套系统,叫A系统吧。
A系统是 国外的产品,开发都在国外。
架构就很简单,用ibm的x86的刀片机,很便宜, 用文件代替数据库,用几十台刀片机,要扩容就多买刀片机就可以了。
很不错。

----------------------------------------------------
各显神通哟,不了解开发,上司就是让用存储过程,我又找不到合适或强有力的说词,唉;不懂开发,没法对比应用与oracle实现业务逻辑的优差性,唉!

列举一个我们的存储过程 ,大体对于每个表皆有select,update,delete,insert对应的存储过程,

--E_TeacherLoginInfo包声明
CREATE OR REPLACE PACKAGE PKG_E_TEACHERLOGININFO
AS
        TYPE entity IS REF CURSOR;
        --创建获取单个实体存储过程声明
        PROCEDURE GETS_E_TEACHERLOGININFO (V_LoginID varchar2, p_rc OUT entity);
        --创建获取单个实体存储过程声明
        PROCEDURE GETM_E_TEACHERLOGININFO (p_rc OUT entity);
        --创建插入的存储过程声明
        PROCEDURE INS_E_TEACHERLOGININFO
        (
                V_LoginID  IN OUT varchar2,
                V_TeacherID  IN varchar2,
                V_LoginName  IN varchar2,
                V_NickName  IN varchar2,
                V_Password  IN varchar2,
                V_IsNormal  IN Char,
                V_LoginStatus  IN varchar2,
                V_Createtime  IN date,
                V_LatestLoginTime  IN date,
                V_LatestModifyTime  IN date,
                V_FailedTime  IN date,
                V_FailedIP  IN varchar2,
                V_FailedArea  IN varchar2,
                V_LatestLoginIP  IN varchar2,
                V_LatestLoginArea  IN varchar2,
                V_Memo  IN varchar2
        );
        --创建修改存储过程声明
        PROCEDURE UPD_E_TEACHERLOGININFO
        (
                V_LoginID  IN varchar2,
                V_TeacherID  IN varchar2,
                V_LoginName  IN varchar2,
                V_NickName  IN varchar2,
                V_Password  IN varchar2,
                V_IsNormal  IN Char,
                V_LoginStatus  IN varchar2,
                V_Createtime  IN date,
                V_LatestLoginTime  IN date,
                V_LatestModifyTime  IN date,
                V_FailedTime  IN date,
                V_FailedIP  IN varchar2,
                V_FailedArea  IN varchar2,
                V_LatestLoginIP  IN varchar2,
                V_LatestLoginArea  IN varchar2,
                V_Memo  IN varchar2
        );
        --创建删除的存储过程声明
        PROCEDURE DEL_E_TEACHERLOGININFO
        (
                V_LoginID  IN varchar2
);
END PKG_E_TEACHERLOGININFO;
/

CREATE OR REPLACE PACKAGE BODY PKG_E_TEACHERLOGININFO
AS
        --查询单个实体存储过程
        PROCEDURE GETS_E_TEACHERLOGININFO(V_LoginID varchar2, p_rc OUT entity)
        IS
                sqlstr   VARCHAR2 (4000);
        BEGIN
                sqlstr :=
                        'Select LoginID, TeacherID, LoginName, NickName, Password, IsNormal, LoginStatus, Createtime, LatestLoginTime, LatestModifyTime, FailedTime, FailedIP, FailedArea, LatestLoginIP, LatestLoginArea, Memo
                from E_TeacherLoginInfo
                where
                        LoginID = ' || V_LoginID;
                OPEN p_rc FOR sqlstr;

        END GETS_E_TEACHERLOGININFO;

        --查询全部实体存储过程
        PROCEDURE GETM_E_TEACHERLOGININFO(p_rc OUT entity)
        IS
                sqlstr varchar(4000);
        BEGIN
                sqlstr :=
                        'Select LoginID, TeacherID, LoginName, NickName, Password, IsNormal, LoginStatus, Createtime, LatestLoginTime, LatestModifyTime, FailedTime, FailedIP, FailedArea, LatestLoginIP, LatestLoginArea, Memo
                from E_TeacherLoginInfo';
                OPEN p_rc FOR sqlstr;
        END GETM_E_TEACHERLOGININFO;

        --插入一行记录
        PROCEDURE         INS_E_TEACHERLOGININFO
        (
                V_LoginID  IN OUT varchar2,
                V_TeacherID  IN varchar2,
                V_LoginName  IN varchar2,
                V_NickName  IN varchar2,
                V_Password  IN varchar2,
                V_IsNormal  IN Char,
                V_LoginStatus  IN varchar2,
                V_Createtime  IN date,
                V_LatestLoginTime  IN date,
                V_LatestModifyTime  IN date,
                V_FailedTime  IN date,
                V_FailedIP  IN varchar2,
                V_FailedArea  IN varchar2,
                V_LatestLoginIP  IN varchar2,
                V_LatestLoginArea  IN varchar2,
                V_Memo  IN varchar2
        )
        is
        begin
                V_LoginID := F_GET_MAXID('E_TeacherLoginInfo');
                Insert into E_TeacherLoginInfo(LoginID, TeacherID, LoginName, NickName, Password, IsNormal, LoginStatus, Createtime, LatestLoginTime, LatestModifyTime, FailedTime, FailedIP, FailedArea, LatestLoginIP, LatestLoginArea, Memo        )
                values(V_LoginID, V_TeacherID, V_LoginName, V_NickName, V_Password, V_IsNormal, V_LoginStatus, V_Createtime, V_LatestLoginTime, V_LatestModifyTime, V_FailedTime, V_FailedIP, V_FailedArea, V_LatestLoginIP, V_LatestLoginArea, V_Memo        );
        end         INS_E_TEACHERLOGININFO;

        --删除单行记录
        PROCEDURE DEL_E_TEACHERLOGININFO
        (
                V_LoginID  IN varchar2
        )
        is
        begin
                Delete From E_TeacherLoginInfo
                        where
                        LoginID = V_LoginID
        ;

        end DEL_E_TEACHERLOGININFO;

        --修改单行记录
        PROCEDURE         UPD_E_TEACHERLOGININFO
        (
                V_LoginID  IN varchar2,
                V_TeacherID  IN varchar2,
                V_LoginName  IN varchar2,
                V_NickName  IN varchar2,
                V_Password  IN varchar2,
                V_IsNormal  IN Char,
                V_LoginStatus  IN varchar2,
                V_Createtime  IN date,
                V_LatestLoginTime  IN date,
                V_LatestModifyTime  IN date,
                V_FailedTime  IN date,
                V_FailedIP  IN varchar2,
                V_FailedArea  IN varchar2,
                V_LatestLoginIP  IN varchar2,
                V_LatestLoginArea  IN varchar2,
                V_Memo  IN varchar2
        )
        is
        begin
                Update E_TeacherLoginInfo
                Set
                        TeacherID = V_TeacherID,
                        LoginName = V_LoginName,
                        NickName = V_NickName,
                        Password = V_Password,
                        IsNormal = V_IsNormal,
                        LoginStatus = V_LoginStatus,
                        Createtime = V_Createtime,
                        LatestLoginTime = V_LatestLoginTime,
                        LatestModifyTime = V_LatestModifyTime,
                        FailedTime = V_FailedTime,
                        FailedIP = V_FailedIP,
                        FailedArea = V_FailedArea,
                        LatestLoginIP = V_LatestLoginIP,
                        LatestLoginArea = V_LatestLoginArea,
                        Memo = V_Memo
                where
                        LoginID = V_LoginID
        ;

        end         UPD_E_TEACHERLOGININFO;

END PKG_E_TEACHERLOGININFO;
/

-------------------------------------------------------
还是tom那段话吧, 能用SQL解决的不要用存储过程,能用存储过程解决的不要用java ,能用java 解决的不要用C,C都不能解决了需要考虑下是否需要实现了

大致是这样。。。
------------------------------------------------------
数据库的扩展成本确实比较高(贼有钱的企业除外),DB服务器永远都比APP的服务器贵。一般都考虑在应用层扩展,在应用层处理,而不考虑将DB复杂化!
------------------------------------------------------
zhangfengh 老狐狸 发表于 2010-6-30 10:33  
找平衡点,要看你的数据库压力到底能达到什么程度,是否真的需要用应用层去分担数据库的压力

如果压力真的那么大,那么利用应用层也无可厚非;如果压力达不到,又何必去用应用层做数据库的事情呢

个人看法:能够用到数据库的功能的还是要尽可能的用。如果数据库仅仅作为一个容器,只是为了保存数据用,那何必用oracle呢,又要花钱买人家的软件,又要花钱买人家的服务。直接存进文本,自己处理岂不是好
------------------------------------------------------------------------------------------------------------
 wuxunhym 巫师勋  发表于 2010-6-30 11:29  

尽管数据库的功能强大,但在OLTP系统里,一个有破坏性的语句能够导致其他语句运行相当缓慢,因此都会尽可能的将语句简单再简单。OLTP系统应该以用户为主要的,这是数据库在整个系统中的宗旨。
应用层相对来说容易扩展,而数据库难一些。 如果在设计时候将压力转向了数据库层面,用户和使用增长到一个数量级后,极有可能还是要回到起点去调整整个架构。何不在设计时候做到相对简单呢……

直接存到文本,当然更省钱省事!不过,这个反例没有说服力。用户怎么怎么查数据呢? 总不能让用户花几十秒甚至更久的时间去找一条数据呀。

 ------------------------------------------------------------------------------------------------------------
 
 lei 发表于 2010-6-30 11:35  
忽然看到这个帖子莫名成精了。


其实事无绝对的。
开发维护角度:看你的开发人员多少,当然也要看你的团队人员的技能构成和水平,根据个人的经验,觉得还是存储过程相比较Java的那些玩艺要容易、轻量、好管理、好沟通、也好分层。
性能角度:看你的软硬件平台能力,看你的数据量来选择架构吧,先期可以开发一个原型模块加足够的压力测试一下,个人觉得,存储过程的性能对一般的封闭系统足够了,从你的那个例子存储过程看,你的系统可能只是基于web的管理信息类系统,而不是像前面贴子里面的阿里公司那样的公众开放系统,所以扩展性的考虑不是第一位的。
 
  ------------------------------------------------------------------------------------------------------------
 fan0124 发表于 2010-6-30 11:49  

不是说要你一定就像淘宝那样去做

第一,你所在的团队的技术积累是没有达到人家那样的高度很深度的

第二,开发团队能够达到用复杂算法及良好的架构来处理很多复杂运行,性能问题吗(比如说实现复杂的在线分析统计),还没有到那个程度,就只

能让DB去处理

第三,最关键的,你的数据量和并发能达到淘宝那么高吗?没有那么高(楼主的系统实时级别,数据量级别应该不大吧,我可以肯定的说)

能用DB抗的住,那你就用DB抗,但是抗不住了,就要考虑在APP应用上扩展

为什么APP扩展容易,一台机器一部署就好了。但是数据库是要复杂多的

第四,建议还是业务逻辑往应用上放
 
   ------------------------------------------------------------------------------------------------------------
首先,估计你的网站规模,用户人数,同时并发数,年增长率
对比你的硬件配置性能,能满足要求就没必要和淘宝之类的网站比
再看你的开发团队,将来的维护吧,这才是最重要的呢
要看多久能够使用户和使用增长到一个数量级,这种预先设计是否适合。如果是两三年就能上一个数量级,那么是一种设计方法,如果十年八年都不一定要上一个数量级,那么又是另外一种设计方法了
另外,淘宝的方法就适用于所有的地方吗?不是的吧。要看你们具体的情况去设计,而不是说淘宝就是那么做的,咱就都要那么做

 
   ------------------------------------------------------------------------------------------------------------
WESTLIFE_XU 小白 发表于 2010-6-30 16:03  

QUOTE:
--------------------------------------------------------------------------------
原帖由 wolfop 于 2010-6-29 14:50 发表
从应用分层的原则,大量使用存储过程导致业务逻辑分散在DB和应用服务器层,肯定不好开发维护和更新。
从性能来说,SP肯定不是最优的,我知道的案例就有某运营商原来计费批价都用SP,后来很难满足性能的问题。
总体来说,SP可以用,但要很慎重,最好只用来维护,不用于业务逻辑和支撑高并发高性能的东西。
--------------------------------------------------------------------------------

没有绝对的东西
不同环境,不同压力下,不同的场景使用合适的技术。
淘宝的数据库压力太大了,自然会尽量想办法降低压力,尽量做到只保存数据,不做其他事情,当然,存储过程也存在难于管理 维护的问题,这个也非常头疼。
 
 
  ------------------------------------------------------------------------------------------------------------

精彩的讨论!
其实,高并发,或者典型的OLTP的网站,后端数据库很容易成为瓶颈。
其实,对于我们来说,跟taobao也有点像,一般需要排序的SQL都不被允许。
  ------------------------------------------------------------------------------------------------------------
dahuzizyd 干死日本人 发表于 2010-7-1 11:36  
简单的sql操作肯定是不必写到存储过程里的。

假设你有1000张表,仅仅是基本的CRUD操作,都写成存储过程就有4000个,那好,我全都封到包里,那也有1000个包。

再来看单表的操作,C,D操作一般有一个,R,U就不好说了,可能A业务select的时候用10个字段,B业务用5个,C业务用3个,每个都写一个存储过程?同理,A业务更新10个字段,B业务更新5个,C业务更新3个,这样一来,单是针对一个表的CRUD存储过程就有可能超过10个。

好,我打个8折,1000张表,8000个CRUD的存储过程。和你真正处理业务逻辑的存储过程搁在一块儿,光找就得半天。

再者,一个表10个字段,写成存储过程,10个字段都作为参数?这样下来接口是很大的,在前台写sql,反正也要把这些内容都准备好的,通过存储过程,无疑把前后台的耦合度加大了。

sql注入的问题,sql注入是在哪里注入的?前台,那就要在前台控制住,后台数据库管这么宽干嘛?
   ------------------------------------------------------------------------------------------------------------
 zhang41082 发表于 2010-7-1 22:47  
1、如果你的系统没有十分的繁忙,用存储过程简单,改个BUG、优化个SQL,只要数据库上面把存储过程改了编译一下就好了,不用几十台的APP SERVER去上线
2、如果系统很繁忙(指这个存储过程很忙),那可能你连编译它的机会都没有,一编译整个库就HANG在那里了,那绝对是灾难,这时候上线就要求你把前台业务全部停下来。而用APP端来实现的话,你就可以一台台的上线,业务总体来说不中断
3、数据库的CPU资源、IO资源非常昂贵,而且数据库又容易成为瓶颈还不容易扩展。所以量大的时候,放到APP好扩展
 
 ------------------------------------------------------------------------------------------------------------
 newkid  发表于 2010-7-2 00:48  

 

QUOTE:
--------------------------------------------------------------------------------
原帖由 fan0124 于 2010-6-29 10:51 发表
在Oracle中,存储过程就是PL/SQL的模块

PL/SQL引擎会执行过程化语句,但它把SQL语句传送给SQL引擎处理,然后SQL引擎把处理的结果返回给PL/SQL引擎。

然后SQL引擎把处理的结果返回给PL/SQL引擎。

PL/SQL和SQL引擎间的频繁切换会大大降低效率。
--------------------------------------------------------------------------------


其他语言就没有切换了?PLSQL至少和SQL是在同一台机器上!


QUOTE:
--------------------------------------------------------------------------------
原帖由 yueyangflash 于 2010-6-29 13:23 发表
将业务放到数据库中去实现  后期维护可能会存在很大的问题!
--------------------------------------------------------------------------------


放到数据库外实现为什么就没问题?


QUOTE:
--------------------------------------------------------------------------------
原帖由 yueyangflash 于 2010-6-29 13:23 发表
程序员看到存储过程可能并不知道这个存储过程是干什么用的!
--------------------------------------------------------------------------------


那我看到一段JAVA也是一头雾水!


QUOTE:
--------------------------------------------------------------------------------
原帖由 dingjun123 于 2010-6-29 14:48 发表

全用存储过程可能会带来的问题比大部分用SQL带来的问题多。除非你们的团队存储过程和性能优化特别猛!~ 因为很多人熟悉SQL,但是不熟悉PLSQL,为什么放弃熟悉的而且很好的东西,去用不熟悉的东西呢?当然可能会用到存储过程的,但是绝对不是全部!~
--------------------------------------------------------------------------------


全用存储过程问题多在哪里?


QUOTE:
--------------------------------------------------------------------------------
原帖由 wolfop 于 2010-6-29 14:50 发表
从应用分层的原则,大量使用存储过程导致业务逻辑分散在DB和应用服务器层,肯定不好开发维护和更新。
从性能来说,SP肯定不是最优的,我知道的案例就有某运营商原来计费批价都用SP,后来很难满足性能的问题。
总体来说,SP可以用,但要很慎重,最好只用来维护,不用于业务逻辑和支撑高并发高性能的东西。
--------------------------------------------------------------------------------


分层也可以分到DB里面。"SP肯定不是最优的", 举个实例看看?有可能是你的SP没写好。


QUOTE:
--------------------------------------------------------------------------------
原帖由 fan0124 于 2010-6-29 15:19 发表
关于存储过程,首先带来的问题就是业务变动,然后数据库扩展,业务扩展

你怎么弄,扩展十几个数据库时,你去把存储过程迁移十几次去?那不把你搞死

如果业务逻辑变化的时候,怎么弄,改存储过程只有

然后就是在并发比较高的OLTP,性能是很差的

还有对测试人员来说,调试时,你还要他专门跑到数据库里去调试存储过程?如果是SQL,他直接跟踪调试就可以了
--------------------------------------------------------------------------------


“存储过程迁移”?数据才有迁移。如果你是说把程序复制到各个库,不用存储过程难道就不用复制了?应用服务器上也得有程序吧!

“如果业务逻辑变化的时候,怎么弄,改存储过程只有”改就改呗,难道放到外面就不用改。

“然后就是在并发比较高的OLTP,性能是很差的”举个实例。

存储过程的调试并不比其他语言更困难。


QUOTE:
--------------------------------------------------------------------------------
原帖由 wisdomone1 于 2010-6-29 17:23 发表
各显神通哟,不了解开发,上司就是让用存储过程,我又找不到合适或强有力的说词,唉;不懂开发,没法对比应用与oracle实现业务逻辑的优差性,唉!

列举一个我们的存储过程 ,大体对于每个表皆有select,update,delete,insert对应的存储过程,

--E_TeacherLoginInfo包声明
CREATE OR REPLACE PACKAGE PKG_E_TEACHERLOGININFO
AS

/
--------------------------------------------------------------------------------


你这个只是TABLE层面的API, 就是所谓的TAPI, 好的做法是TOM提倡的XAPI, 即事务级别的API. 事务里面可能有多个SQL, 直接写就是,不必再弄一层表级的API.


QUOTE:
--------------------------------------------------------------------------------
原帖由 fan0124 于 2010-6-30 11:49 发表
不是说要你一定就像淘宝那样去做

第一,你所在的团队的技术积累是没有达到人家那样的高度很深度的

第二,开发团队能够达到用复杂算法及良好的架构来处理很多复杂运行,性能问题吗(比如说实现复杂的在线分析统计),还没有到那个程度,就只

能让DB去处理

第三,最关键的,你的数据量和并发能达到淘宝那么高吗?没有那么高(楼主的系统实时级别,数据量级别应该不大吧,我可以肯定的说)

能用DB抗的住,那你就用DB抗,但是抗不住了,就要考虑在APP应用上扩展

为什么APP扩展容易,一台机器一部署就好了。但是数据库是要复杂多的

第四,建议还是业务逻辑往应用上放
--------------------------------------------------------------------------------


应用服务器不是最后也要访问DB? 一个事务如果用到10个SQL, 放到应用服务器也是一样,一个都跑不了,最终压力还是会落到DB.


QUOTE:
--------------------------------------------------------------------------------
原帖由 horizon 于 2010-6-30 14:23 发表
用存储过程移植会出现大问题,可能要重写存储过程也说不定
但应用程序改动会少
--------------------------------------------------------------------------------


如果你说的是换数据库,趁早打消这个念头,不管怎么做都是很困难的。TOM的书专门有一节讲到为什么独立于数据库的想法是不现实的。
PLSQL实际上更为“通用”,在任何操作系统的ORACLE都一样运行;所有的开发语言都可调用存储过程。


QUOTE:
--------------------------------------------------------------------------------
原帖由 dahuzizyd 于 2010-7-1 11:36 发表
简单的sql操作肯定是不必写到存储过程里的。

假设你有1000张表,仅仅是基本的CRUD操作,都写成存储过程就有4000个,那好,我全都封到包里,那也有1000个包。

再来看单表的操作,C,D操作一般有一个,R,U就不好说了,可能A业务select的时候用10个字段,B业务用5个,C业务用3个,每个都写一个存储过程?同理,A业务更新10个字段,B业务更新5个,C业务更新3个,这样一来,单是针对一个表的CRUD存储过程就有可能超过10个。

好,我打个8折,1000张表,8000个CRUD的存储过程。和你真正处理业务逻辑的存储过程搁在一块儿,光找就得半天。

再者,一个表10个字段,写成存储过程,10个字段都作为参数?这样下来接口是很大的,在前台写sql,反正也要把这些内容都准备好的,通过存储过程,无疑把前后台的耦合度加大了。

sql注入的问题,sql注入是在哪里注入的?前台,那就要在前台控制住,后台数据库管这么宽干嘛?
--------------------------------------------------------------------------------


把所有CRUD都做成存储过程不是办法;存储过程应该以事务为单位。
参数也可以用OBJECT来传递,类似PLSQL的记录类型。
如果你的应用服务器被攻击了,别人可以上传脚本做DML那就很危险。把表的权限都收回,只留下存储过程接口相当安全一些。


QUOTE:
--------------------------------------------------------------------------------
原帖由 zhang41082 于 2010-7-1 22:47 发表
1、如果你的系统没有十分的繁忙,用存储过程简单,改个BUG、优化个SQL,只要数据库上面把存储过程改了编译一下就好了,不用几十台的APP SERVER去上线
2、如果系统很繁忙(指这个存储过程很忙),那可能你连编译它的机会都没有,一编译整个库就HANG在那里了,那绝对是灾难,这时候上线就要求你把前台业务全部停下来。而用APP端来实现的话,你就可以一台台的上线,业务总体来说不中断
3、数据库的CPU资源、IO资源非常昂贵,而且数据库又容易成为瓶颈还不容易扩展。所以量大的时候,放到APP好扩展
--------------------------------------------------------------------------------


如果你允许新旧版本程序一起跑,才有可能把APP逐个更新。
 
 ==========================================================
langzhi000 发表于 2010-8-2 10:37  
赞同存储过程以事务为单位。复杂的逻辑处理(比如update,insert较多)的一次事务处理,可以使用存储过程来封装,一方面可以降低应用程序和数据库之间爱你频繁多次交互,另一方面性能上比多次提交sql好很多,还有就是如果发生网络,服务器,程序错误需要事务回滚较容易。至于程序理解上也不一定很难以理解,一方面例如一个订单提交的事务,orderInter,这样的名字在程序里是很好理解的,二来PL/SQL开发人员的开发文档是否能清楚的说明问题也很重要
至于pl/sql解释器,在10g上有了本地编译来很好的解决这个问题。
关于PL/SQL的事务,在一般的互联网企业并不适合全部或大规模的采用,首先开发成本很高,性能又做不到最好,二来互联网企业对数据的完整性要求并不好,允许一定比例的数据错误(一般通过维护时修正)。当然电子商务类的网站还是建议用PL/SQL封装较复杂的逻辑(在使用oracle的情况下)。
 
===========================================================
xpchild 发表于 2010-12-29 18:38  
我觉得;

1,按照分层的原则,一个大型的scalable的web 2.0项目,目前大都采用的至少三层原则,但这并不是说层越多越好,因为交互也是有开销的,但是一个层面就让它解决分内的事情,这样会比较清晰。
2,在业务量和访问量上去的时候,你会发现数据库往往会成为瓶颈,所以业务的处理就尽量在中间件中,业务逻辑层处理,数据库越简单越好,简单就是最美的。
3,oracle的官方文档,或者tom的书中都说建议使用存储过程,给出的理由是你花了钱,就应该充分的使用oracle的特性。这点明显都点广告的味道。

最后:过多的使用存储过程,把oracle变的异常的庞大,增加了管理成本,不利于scable。
 
 ===========================================================

qingyun 发表于 2011-1-7 22:42  

QUOTE:
--------------------------------------------------------------------------------
原帖由 xpchild 于 2010-12-29 18:38 发表
我觉得;

1,按照分层的原则,一个大型的scalable的web 2.0项目,目前大都采用的至少三层原则,但这并不是说层越多越好,因为交互也是有开销的,但是一个层面就让它解决分内的事情,这样会比较清晰。
2,在业务量和访问量上去的时候,你会发现数据库往往会成为瓶颈,所以业务的处理就尽量在中间件中,业务逻辑层处理,数据库越简单越好,简单就是最美的。
3,oracle的官方文档,或者tom的书中都说建议使用存储过程,给出的理由是你花了钱,就应该充分的使用oracle的特性。这点明显都点广告的味道。

最后:过多的使用存储过程,把oracle变的异常的庞大,增加了管理成本,不利于scable。
--------------------------------------------------------------------------------


2.在业务量和访问量上去的时候,,本质就是 update,insert 一坨坨SQL频繁的提交; 如果写在中间层,用java 动态拼一坨坨字符串,然后一条一条的和DB交互10次;
好“伤”数据库啊 ,这个瞬间大量的java产生的sql字符串,通过jdbc 高速的与数据库交互 ,不如封装层存储过程;减少通讯量;
毕竟PLSQL的引擎是对于SQL的切换内部的;而java与数据库的引擎要比他慢的多;

最后,过多的在中间层是使用一坨坨杂乱如麻的动态字符串SQL,把oracle的SQL变的异常的庞大,出了问题维护麻烦,很难找出那些sql写的有问题;

 

很多人都觉得,中间层业务服务器,可以很好的分担数据库的压力;
也就是说:本来 数据库 一个人在干活,现在来了N个中间业务服务器,那么就是N+1人在干活;数据库服务器他就只需要干1/(N+1)的事情;
         那是细想一下,可能吗? 中间业务数据库,大部分时候是把一坨坨动态SQL字符串,通过jdbc这样低效的驱动,不停的对  数据库这个人 拼命的要求update之类;

也就是说:如果用存储过程封装,相当于领导(客户端)分配一件事情给你,你做好后提交即可;

   而用中间层动态SQL来封装业务,相当于领导(客户端)分配一件事情的时候,没有直接给你,而是给了几个中层领导;这几个中层领导自己也不会做,而是把这件事分解成很多小事情,
不停的一件件的问你或者要求你去做; 结果本来一件不是很复杂的事情,很快能做完的; 但是经过几个中层一折腾,反而经过了很多手续和过程,导致了中层领导很累,你也跟着很累;
 
 QUOTE:
--------------------------------------------------------------------------------
原帖由 horizon 于 2010-6-30 14:23 发表
用存储过程移植会出现大问题,可能要重写存储过程也说不定
但应用程序改动会少
--------------------------------------------------------------------------------


用存储过程移植会大大方便;
  1.大部分系统,前台可能,今天用java,明天用c#,后天用php,或者是多种前台程序混合成一个系统;但是数据库不会轻易变;
在这种情况下,如果业务实现都用存储过程实现,那么移植只是修改一些外围的调用程序,而且就算这些前台开发者的水平烂,
但是存储过程逻辑严谨的话,不会产生异常的逻辑数据;

  2.存储过程,能够被任何前台语言调用,能够在任何操作系统下使用;


  3. 存储过程修改很方便,不用发布,就是脚本重新编译下而已; 现在不是流行动态脚本语言吗? 存储过程不就达到这个效果吗;


4.先不考虑运行效率;光开发效率来说,存储过程开发速度最快,因为只要是开发人员,是人都懂SQL, 对于oracle,PLSQL很容易学的,理论上一天就能学会;
  而那么多的前台语言,要深入进去,那个不需要3年5载; 而存储过程写的很好的话,半年一年就很强了;


5.不要把写复杂SQL,写存储过程当做是DBA的事情,放眼望去,95%的人都是做开发的,单纯的做DBA的人很少,而且时代发展,就算是强人DBA,必然有很强的开发能力;
就像牛顿,物理上取得了很大的成就,必然有很强的数学能力做基础。
是人都会写SQL, 不会写SQL还能做开发,尤其是面向数据库为主的应用系统;
  凡是资深的开发人员,一般都会有某一两门很擅长的前台开发语言技能;但都不会缺少最基本的技能,就是很强的SQL开发能力,如果SQL很强,存储过程能力自然也会很强;

 =============================================================================
 monkeyai 发表于 2011-2-18 18:07  
这个其实没太多争论余地吧。

如果是典型的WEB引用,一般没必要用存储过程,OLTP类型的事务一般都很简单,涉及数据量小,而且前端用户基本都是通过WEB界面操作,不可能直接输SQL语句吧,至于所谓绑定变量以复用SQL语句之类问题,应该可以在应用层实现,要是前端应用都是硬编码那怎么也没办法的;

如果是OLAP或者DW这类大数据量处理,那PL/SQL用的就比较多了。因为1、可能有比较复杂的处理,单条SQL逻辑实现不了;2、对于大数据量,直接用单挑语句可能超出系统硬件能力,搞点回滚段过旧之类问题出来;
 
 ===========================================================================
1060406004020 发表于 2011-3-17 17:34  
本人总结出以下几点,是存储过程比sql要好的地方
1、        存储过程可以用流语句编写,具有很大的灵活性,如果业务逻辑要完成一个很复杂的数据库操作,那么使用存储过程,你只需要在应用端输入参数直接调用就行,那岂不是很方便?但是你要通过sql的话,那就不知道要定义多少个String了,然后通过jdbc与数据库进行通讯。
2、        使用存储过程可以降低网络的通信量,当你使用存储过程时,jdbc完成的只是对存储过程的调用,而使用sql语句时,每条操作语句都要和数据库进行一次通讯,那不但会增加应用服务器的压力,而且大大增加了网络通讯量。
3、        在运行存储过程之前,数据库已经对存储过程进行了预编译,并给出了优化方案。所以他会改善了sql语句的性能
4、        存储过程可以保证数据的安全性和完整性。安全性就是使没有权限的用户间接地存取数据,完整性就是可以使一组相关的动作一起发生,这个有点类似于事物的概念。
 
==========================================================================
直接放存储过程里,是要消耗资源的,存储过程不是万能的,虽然他有很多好处,存储过程中PLSQL引擎与SQL引擎的交互不需要时间?可能大部分时候写存储过程和SQL代码效率差不了多少,但是很多时候存储过程就差多了!如果直接把代码写在页面里,我当然不干了啊,看起来都头疼!你说的调用存储过程,还是需要服务器端语言与Oracle交互的啊,你这个交互的次数更多了!
服务器语言里的SQL----Oracle SQL引擎
服务器语言里的PLSQL----Oracle PLSQL引擎----Oracle SQL引擎
===========================================================================
killkill_shadow 发表于 2010-7-29 00:27  
先不说性能和逻辑究竟应该放在应用层还是plsql过程中这两个问题,我先说说近日遇到的一个问题:

近日发现数据库的CPU占用很高,用AWR找出Top SQL然后开始调优,但是这条语句有一个
dbms_lob.instr( userid_list , userid )
开发商把userid串接成一个字符串放在userid_list里面,userid_list是clob类型读取时默认触发 direct path read,再查I/O发现磁盘每秒读取60~70 MB,修改存储属性,让clob也能缓存在内存中,但是该死dbms_lob.instr( userid_list , userid )导致了一张一万多行的表扫描4次,一万多行不多,问题是每行都起码有一个clob(8k),估计CPU就是在这里面耗完的。
联系开发商改应用,估计拖到猴年马月,自己改又没有源代码,建索引 dbms_lob.instr( userid_list , userid ) 怎么弄?其他涉及的字段选择性及其差,都是状态字段。
现在只能说俺们机器和存储比较好,硬撑这个SQL。

如果对外只是提供过程作为接口,那好办,方法多了,废掉这个表,把userid_list拆开按照范式做,建立相应的索引,用userid查,那根本就不是什么难调的SQL;不改表,在这个表加触发器,增删改都修改另一个范式的 userids 表,再改SQL把dbms_lob.instr( userid_list , userid ) 改成搜索遵守范式的表;再不行,上全文索引,把dbms_lob.instr( userid_list , userid )改成 contains(userid_list , userid);
方法多的是,把过程或者SQL放在数据库一级关键是实现了接口与具体实现的分离,深奥一点的说法是,用接口把调用和具体实现隔离,GOF的设计模式中很多都是在实现变与不变的分离,策略模式,模板方法模式,工厂模式等等就是最好的例子。

再说远一点,贪方便把SQL放在页面或者应用中开发速度是快,ASP年代MS也是这么想的,自从JSP崛起,以及ASP.net哪一个不是搞分层?
层与层之间的调用哪个不是通过接口隔开,不用接口隔开就和一堆类调用另一堆那样,最后变成一碗兰州拉面一样。

说回刚才那件事,现在的状况就是应用对于DBA来说就是一个黑盒,接口就是那条SQL语句,你不能动,只能动数据的一些存储结构,例如索引,表类型等,处处受限。
 
 ===========================================================================
whw_0501 2010-7-29 01:15  
项目一般用MVC模式,我们一般都会写一个数据库访问接口公共类,平常的SQL语句我们都放在service层,对于过程来讲,我们也放在service层,由service层调用数据访问接口

 whw_0501  发表于 2010-7-29 01:15  
项目一般用MVC模式,我们一般都会写一个数据库访问接口公共类,平常的SQL语句我们都放在service层,对于过程来讲,我们也放在service层,由service层调用数据访问接口

 
 
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值