存储过程与SQL语句的恩怨情仇

程序员说:存储过程还是SQL语句,这是一个问题。
江湖现在有三个流派,一个是SQL语句流的,崇尚使用SQL语句,一派是存储过程派的,崇尚用存储过程说话,还有一派是中庸派的,讲求和谐,所以也就前两派吵得厉害,中庸派的看热闹。现在SQL派的有Nhibernate为首的众多ORM助阵,最近风生水起比较得意,存储过程派也有自己的杀手秘籍,两派互不相让,争斗由来已久。
存储过程派的追求速度,所谓天下无功无坚不破,唯快不破,这也是存储过程派的人行走江湖的最大本钱。之前存储过程派的攻击SQL语句派的还有一个秘籍就是安全,不过现在都没人用连接String的动态SQL的了,这招也就失效了。
SQL语句派是资格很老的流派,但是新手居多,老资格很多投奔敌营存储过程派了。Java帮的人很多都是SQL语句派的,而存储过程派的以微软帮的居多。
不过存储过程派也有软肋,可移植性就是其一,还有一点就是可扩展性,因为一般大型的Web应用程序都是多Web服务器,然后用双数据库服务器做双机热备,其中一台开机,但是是闲置的,这里只是解决单点故障的问题,但是形成了多Web应用服务器,单数据库服务器的情况,如果所有的运算都用存储过程实现,那么会造成数据库服务器负担过重,而Web服务器负荷不足的情况,而扩展数据库服务器的话就会非常的麻烦,而且投资较大,程序也需要改,而投资Web服务器就相对便宜而且扩容更加简单。
人在江湖漂哪有不挨刀,所以中庸一点比较保险,我比较倾向于用把较多的负担放到程序里来,而降低数据库得负担,因为只要数据库扛得住,再增加Web服务器那是比较容易的,但是一旦数据库服务器扛不住了我们就只有哭了。一般报表阿,还有一些结果集比较复杂的我就用存储过程来包装,一般的查询和CUID操作我都是找个ORM来搞定。

其实主要是在说存储过程的软肋。

posted on 2007-04-01 17:26 亚历山大同志 阅读(5002) 评论(44)  编辑 收藏 所属分类: 随笔

评论

#1楼  2007-04-01 17:37 布尔      

根据需要而做既可,没有那么多时间考虑啦   回复  引用  查看    

#2楼  2007-04-01 18:54 Samuel      

得看具体情况来。
做的多了,反而觉得存储过程好。

  回复  引用  查看    

#3楼  2007-04-01 18:59 Clingingboy      

HOHO,两派兼修啊   回复  引用  查看    

#4楼  2007-04-01 19:59 rehearts [未注册用户]

什么文章啊,   回复  引用    

#5楼  2007-04-01 20:59 Clark Zheng      

“据说如果所有网页都用黑色背景可以节约好多亿千瓦的能源,所以换了个黑色背景的SKin”,这句话害我不浅。。。

不过文章写的有意思!   回复  引用  查看    

#6楼  2007-04-01 21:05 鱼是飞的      

I am One Of Procedure Community!   回复  引用  查看    

#7楼  2007-04-01 21:34 小鬼 [未注册用户]

加数据库真的很麻烦吗?   回复  引用    

#8楼  2007-04-01 21:40 kiler      

在存储过程这个问题上还是比较支持楼主的,我觉得存储过程除非在使用SQL语句性能无法接受的时候才能用,一般情况下能不用就不用。   回复  引用  查看    

#9楼  2007-04-01 23:14 谢星星      

呵呵,实际应用中的性能决定!呵呵   回复  引用  查看    

#10楼  2007-04-01 23:31 曲滨      

呵呵我个人
还是喜欢用 Pet Shop 那种简单工厂模式,不用写太多存储过程
也不用什么 Nhibernate

Nhibernate 性能不好,看似支持 n多数据库,不过实际应用项目大了也问题多多

光用存储过程影响服务器
存储过程派推荐使用 Enterprise Library Data Access Application Block
支持多种数据库链接,不过各种 sql 语句没法通用,这东西也是给存储过程优化的基本上,不过对于不同的数据库要写n套存储过程

这个世界上没完美的

简单工厂模式:如果没有代码生成器就手写代码就很郁闷了 ,不过可以先不考虑多数据库做完一个在作一个dal 即可。




  回复  引用  查看    

#11楼  2007-04-02 07:58 小哈      

字體選的是哪一種啊?
看起來很順眼^_^   回复  引用  查看    

#12楼  2007-04-02 08:56 jillzhang      

其实就那么几点区别:
1)从部署上看,存储过程要比sql难
2) 从性能看,存储过程要比SQL高
3) 从安全性将,存储过程比SQL防注入
根据具体需要,具体选择吧   回复  引用  查看    

#13楼  2007-04-02 09:35 eee [未注册用户]

如果用了Replication, 修改或者添加存储过程还不就是小菜了   回复  引用    

#14楼  2007-04-02 09:40 kiler      

@jillzhang
2) 从性能看,存储过程要比SQL高
不见得,有的人写存储过程会参杂很多业务逻辑的处理,这样写出来的存储过程速度不一定比用sql写快。而且在小数据量下的插入、更新、删除、选择操作,存储过程比sql没有多大的性能优势,我以前测试的时候甚至出现过用sql比存储过程还快的情况。

3) 从安全性将,存储过程比SQL防注入
安全性完全是一样的,SQL语句也可以用参数的,同样有的人用存储过程照样是在用sql语句拼接(如分页存储过程),所以存储过程的安全性和sql是一样,没有区别。   回复  引用  查看    

#15楼 [楼主] 2007-04-02 09:46 亚历山大同志      

@kiler
大学里学Oracle的时候还有MCSE学SqlServer的时候都提到过,数据库一般会将使用过的Sql编译后缓存起来,在第二次执行的时候会快很多,不知道是不是这个原因   回复  引用  查看    

#16楼  2007-04-02 09:46 e表      

写sql比写存储过程方便!! (纯.net写的web报表开发工具: http://webreport.fcsoft.com.cn/ )   回复  引用  查看    

#17楼 [楼主] 2007-04-02 09:47 亚历山大同志      

@e表
呵呵,你的广告还真是无所不在阿   回复  引用  查看    

#18楼  2007-04-02 09:52 金色海洋(jyk)      

该用什么就用什么。
我的程序里面SQL居多,存储过程作为辅助。
因为我的程序不太复杂,所以存储过程用得很少。
至于添加修改,写一个表单控件就可以了。   回复  引用  查看    

#19楼  2007-04-02 10:16 kiler      

@亚历山大同志
我那次测试基本上是在存储过程已经使用了以后再进行的,所以可以排除你说的这种情况了,我测试的数据量比较小,基本是单条数据的插入,修改,删除,选择,以及100条以下数据的查询,测试结果是基本上所有的操作时间只相差。0.0几毫秒,其中插入数据的操作用sql还快一点(也是就是快0.0几毫秒),我想说的是在小数据量的情况下,存储过程与sql比起来是没有优势的。其实我们在做开发时候大部分情况下还是以这种小数据量为主,所以我们没有必要非用存储过程不可。当然当我们处理比较大的数量的时候(超过10w),这个时候存储过程的优势就体现出来了,我们就可以考虑使用存储过程了。   回复  引用  查看    

#20楼  2007-04-02 11:38 jillzhang      

@kiler
您说的也没错
但性能上,个别情况不能说明整体问题。
  回复  引用  查看    

#21楼  2007-04-02 13:33 .net开发资源精华收集 [未注册用户]

偶属存储过程派:)性能和速度第一,移植性一般不用考虑,基本上都是SQL Server。   回复  引用    

#22楼  2007-04-02 15:34 域名注册 [未注册用户]

牛   回复  引用    

#23楼  2007-04-02 17:46 skyakira      

算是中庸的一派,复杂的用存储过程搞定,简单的用语句搞定;   回复  引用  查看    

#24楼  2007-04-02 19:28 Artech      

SQL 和SP视情况而定,但我始终不赞成把SQL写在Code中间,会造成Code很难维护。如果必须使用SQL,我一般会把SQL写在一个XML中。   回复  引用  查看    

#25楼  2007-04-02 23:41 volnet(可以叫我大V)      

不过现在都没人用连接String的动态SQL的了

本人愚钝,不知道这个是什么样子,能否举例   回复  引用  查看    

#26楼  2007-04-03 09:04 ddr888      

最近用存储过程多些 的确sp调试是个很大的问题。有时候郁闷一下午才憋出一个sp。   回复  引用  查看    

#27楼  2007-04-03 09:06 zxy [未注册用户]

sql = String.Format(@"Select * From tables Where tableID = {0}",tableId);
-----------------------------------------------------------------
StringBuilder strSql=new StringBuilder();
strSql.Append("UPDATE Detailed SET ");
strSql.Append("Content=@Content");
strSql.Append(" WHERE DetailID=@DetailID");   回复  引用    

#28楼  2007-04-03 11:12 飞鱼 [未注册用户]

反驳一下:
首先声明我支持存储过程,其有不可替代的作用。用存储过程理由如下:
1.效率,楼上几位分别举例说Sql语句比存储过程效率高什么的,如果对于同一条语句连续执行得到的平均值可能跟存储过程差不多,为什么?原因是对于同一条Sql语句数据库不会每次都编译,但是如果每次不一样呢?比如查询一个ID为XXX的产品每次ID都不一样,这个时候SQL语句效率就明显不如存储过程了,因为存储过程是一次编译。

2.部署问题:如果用SQL语句的话不管你把Sql语句放到什么地方总之在数据库发生变化时如:从MSSqlServer迁移到Oracle时你的程序中所有的Sql语句都要改,你可能说这个我可以集中存放,不错但是会对程序员的要求提高。

3.安全问题:不错 在SQL中可以用参数形式,不过这个得要求程序员必须采取这样的形式,如果刚来的程序员不知道,倘若采用了非参数方式,那你的程序很可能有注入的可能。存储过程不会出现这种情况!   回复  引用    

#29楼  2007-04-03 13:06 kiler      

@飞鱼

1.先声明一点,我没有认为sql语句的效率更高,我的意思是在小数据量操作情况下存储过程性能优势不明显。

2.部署方面,首先关于你说那个把数据库从MSSqlServer迁移到Oracle需求,对于这样的需求一般就差不多要重写代码了,以前的存储过程基本上没有什么用了,MSSqlServer和Oracle之间差别很大的,他们之间很多字段类型都是不一致,他们的主键生成策略也是不一样的,MSSqlServer的存储过程根本没有办法直接在Oracle上用,甚至连存储过程的方法接口也不一定能保留下来,所以说存储过程基本没有可移植性。还有一点使用存储过程的在维护的时候也挺麻烦的,每次新增或者修改存储过程,都要记下来然后再更新到生产系统,如果我用sql,我只需要更新一下dll就可以了。

3.安全问题我说过了,照样有人在存储过程拼接sql,存储过程一样的可以注入sql,像现在比较流行的分页存储过程就是很典型的拼接sql的存储过程,存储过程和sql安全性没有区别。不相信的话,你可以看看这篇文章
http://www.cnblogs.com/yukaizhao/archive/2007/03/09/pagination_proc_problem.html
现在n多人写存储过程其实就在存储过程里面写exec (@strSQL)来执行sql语句,这和写sql有什么区别。

存储过程唯一的优点就是性能好的,但是为了这点性能提高破坏系统的可维护性,实在不值得,我的观点还是存储过程要慎用。

  回复  引用  查看    

#30楼  2007-04-03 13:20 Cure      

我觉得从抽象层次上两者都是一样的,开发起来谁比谁快不了多少,差别主要在个人习惯,其他的都不是最主要的问题。sql注入是程序员代码的漏洞,而不应算在sql语句本身的头上。
存储过程还是让DBA去搞吧,我们程序员就用sql语句好了。   回复  引用  查看    

#31楼  2007-04-03 16:21 金色海洋(jyk)      

1、效率。如果一个数据库里有一个存储过程,那速度一定很快:但是如果有100个呢?1000个呢?速度还会依然的快吗?另外存储过程越多占用的内存也就越大。

2、SQL语句写在code里的话,当迁移数据库的时候,不是100%都需要修改的,如果编写的时候注意一下的话,需要修改的地方就不会太多。
另外可以把SQL语句提出来呀,可不是把它提出来放在单独的代码文件里,而是放在XML这样的“配置文件”里面。这样的话即使改也不需要重新编译。

3、安全方面嘛,说的是注入攻击吧,这个和存储过程或者SQL语句没有关系。
这完全是程序员的事情!程序员遥对得到的数据进行验证,保证不发生危险。这是程序员在调用存储过程或者是拼接SQL语句是要做的事情!

  回复  引用  查看    

#32楼  2007-04-03 16:31 金色海洋(jyk)      

还有一个问题,执行密度的问题,就是说一秒钟内,执行存储过程(或者SQL语句)多少次,简单的说就是一秒钟有多少人来访问。

如果一秒执行一次的话,二者在反应速度上会有差别吗?
如果一秒执行500次的话,那么效率的差距就体现出来了。

不过有这么高的访问量的话,就要考虑是不是要用其他的方法(比如静态页)来缓解压力了。


  回复  引用  查看    

#33楼  2007-04-03 21:25 zxbyh [未注册用户]

哈哈!!该用存储过程的时候,用存储过程,该用Sql的时候用sql
我个人非常痛恨两个极端:如下

唯存储过程论者的极端:

对一个表的添加删除修改,都些成存储过程,如果那个表有30个字段,那个存储过程就有30个参数. 无语!!

唯Sql论者的极端:

一个应用,需要从几个表里面查询,同时要DML几个表
然后都写在程序里面,然后和数据库来回10多次,我晕!

其实看了上面两极端,就应该明白什么时候该用存储过程,什么时候不该用存储过程!


  回复  引用    

#34楼  2007-04-03 21:28 zxbyh [未注册用户]

金色海洋(jyk)
1、效率。如果一个数据库里有一个存储过程,那速度一定很快:但是如果有100个呢?1000个呢?速度还会依然的快吗?另外存储过程越多占用的内存也就越大。
----------------------------------
存储过程越多占用内存越多这个有一定道理,从Oracle来看,存储过程多,会让数据字典变大,而数据字典是在SGA里面的!
但是话又说回来,存储过程都是一些文本,1000个也不会占用多少内存哟!!   回复  引用    

#35楼  2007-04-03 21:31 zxbyh [未注册用户]

不过存储过程派也有软肋,可移植性就是其一,还有一点就是可扩展性,因为一般大型的Web应用程序都是多Web服务器,然后用双数据库服务器做双机热备,其中一台开机,但是是闲置的,这里只是解决单点故障的问题,但是形成了多Web应用服务器,单数据库服务器的情况,如果所有的运算都用存储过程实现,那么会造成数据库服务器负担过重,而Web服务器负荷不足的情况,而扩展数据库服务器的话就会非常的麻烦,而且投资较大,程序也需要改,而投资Web服务器就相对便宜而且扩容更加简单。
--------------------------------------------------------------
这种情况,对于Sqlserver做数据库的大型Web应用的确又这个缺点.
但是如果是Oracle的应用就不的这个问题了,RAC就是这样的应用,多个实例可以在不同的机器上,分担负载

所以我一直不喜欢Sqlserver做大型数据库应用!!   回复  引用    

#36楼  2007-04-03 21:46 xpeter [未注册用户]

我喜欢SQL server
至少它的DTS和XML QUERY好用。
我偏向存储过程,至少有一个好处是可以尽量把数据级操作放在数据库那边,前台程序里面很清爽,不需要混杂着一些SQL,简单的数据操作交给存储过程,复杂的交给DATA FLOW和DTS。   回复  引用    

#37楼  2007-04-03 21:51 zxbyh [未注册用户]

中小型数据库应用Sqlserver还是非常愉快的!


DTS是好东东!!   回复  引用    

#38楼  2007-04-03 21:52 天轰穿      

我不乱说话,但是凡多次复用的我都尽量用存储过程,毕竟写得麻烦。

但是正常情况还是顺手就SQL语句!   回复  引用  查看    

#39楼  2007-04-04 11:11 小陆      

业务逻辑无论是写在sql还是存储过程中都是不对的,这样会对程序的结构造成很坏的影响。
数据表是无法正确的表达一个业务实体的。首先,数据表只能表示数据,无法体现数据的含义(比如一个数据库字段叫做sex,内容有1和2,你无法知道1和2到底代表什么,而业务实体则是可以解释自己的),其次数据表的设计受到范式的约束,无法很好的体现业务意义(比如在业务概念上,“发票”是一个完整的概念,但是在数据库里,必须考虑到存储的特点,是不能设计成一个表的)。
存储过程应该用来处理数据,千万不能处理业务。   回复  引用  查看    

#40楼  2007-04-05 18:32 曲滨      

我再来补充一下
移植性的问题

存储过程
1) 数据库迁移,如果不是设计时就考虑好:多半都会连存储过程代程序一起重写
前提:
A)设计时必须对你要移植的数据库了解,知道那些类型是大家都有的那些类型是没有的
B)设计时就要知道代码实现是否是可移植的、也就是说在你写 SQL Service存储过程的时候,就能想到如果是 Oracle 或 DB2 的存储过程一样的业务基本应该如何实现,如果不能实现怎么用程序代码进行补充。
如果不满足以上两点,就等着代码,存储过程都重写吧
如果做到了,基本代码不用动,只重写全部的过程即可
不过上面这几点,必须是经常使用多种数据库的人才可做到、只用过 一种的就不用想了,


还是乖乖的去用 Pet Shop 那种简单工厂模式去吧。

Nhibernate 等 orm 框架现在来说也不是移植性能很好,因为这些东西,性能太垃圾、而且功能都是取的数据库的交集,就是说根本利用不上数据库的特有功能


而且还有一个时间因素在里面,不管代码也好,存储过程也好
如果过了几年,就不一定怎么回事了。

还有 存储过程也应该划分开的和代码一样,如果很大业务逻辑堆在一个过程里
千八百行的。过一年半年的让你重写成其他数据库的相同的存储过程,那一定是一场恶梦,如果让别人从写基本没戏
不过这个问题代码也存在,不过 存储过程更容易写成这样。

最终结论

世界上没有灵药
很多东西不是完全取决于用什么的,用什么只是30%或更少
最重要取决于人本身,就是说这些东西谁来用
还有就是业务是什么样的

计算机是死的程序员是活的
不要去论证什么东西“最应该”,“最应该”是根据实际情况而定的



  回复  引用  查看    

#41楼  2007-08-19 22:47 zzzzz [未注册用户]

如果sql语句过长,我就用存储过程,如果数据库压力大,web服务器可以考虑缓存,静态。   回复  引用    

#42楼  2007-08-22 20:28 wwl      

自已觉得拉堆屎出来都是好东西。。。   回复  引用  查看    

#43楼  2008-02-22 00:17 y557289 [未注册用户]

怎么经常看到这样的议论啊。。我觉得做项目很多时候根本不是自己说了算的,是老板让用什么就用什么、客户让用什么就用什么。如果老板没有规定、客户没有规定,就在性能、可扩展和自己的顺手度上取个折衷。还有如果在数据表里适当的加一点冗余列和冗余表,再加上缓存依赖、页面缓存、GZip和静态化以后,小数据量的存储过程和SQL参数的执行效率差别不大的。当然10W条以上的数据偶不敢说,偶才疏学浅,10W以上的数据量还没接触过。。。请各位大哥大姐指教了^^   回复  引用    

#44楼  2008-02-23 11:16 小眼睛 [未注册用户]

@y557289
有时候客户也是听别人忽悠的 , 呵呵 , 看情况定 ,各取所需   回复  引用    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接:
 


导航

公告

鉴于很多TX投诉黑色背景杀伤眼球,遂换个容易阅读的
!!八强八强!!!!!!! 8-16 21:40
<2007年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

统计

与我联系

搜索

 

常用链接

留言簿(25)

我参加的小组

我的标签

随笔分类(80)

随笔档案(80)

相册

朋友的Blog

同事的Blog

最新随笔

积分与排名

最新评论

阅读排行榜

评论排行榜

60天内阅读排行