随笔 - 29  文章 - 1 评论 - 180 trackbacks - 3
<2007年11月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

欢迎访问我的非技术博客:
http://Moosdau.blog.163.com

与我联系

常用链接

留言簿(2)

随笔分类(28)

随笔档案(29)

搜索

  •  

最新评论

阅读排行榜

评论排行榜

针对这个问题再写一篇文章讨论, 自己也觉得多余, 不过, 由于上一篇中我表意不清, 同时掺杂了一点我对存储过程的不满, 导致整篇文章的中心意思偏离了主题, 在讨论的过程中, 更是越偏越远, 到最后, 连我自己都几乎忘了我的本意. 因此, 觉得有必要再次阐述我原本的立意.

自杀用长枪好,还是用短枪好? 我的回答是, 不要自杀. 这个回答并不真的是客观地评论哪种枪更适合于自杀, 而是, 我根本不关心这件客观的事情, 我的态度是从另一个角度, 说这件事情根本不该发生. 同样的, 其实对于存储过程和sql 语句, 我并不是想去真的挑起它们之间谁更优秀的争吵, 而是说, 在多数情况下, 根本不该去写那样的存储过程.

是的是的, 我绝对承认, 对于几十几百行的存储过程 , 如果把它们拼成字符串由web端提交, 效率肯定会大大低于存储过程, 而我想说的是, 这几十几百行的存储过程, 应该换成一行sql 语句, 其它的部分, 不要由数据库来处理.

这个结论, 以及所有的讨论, 所基于的环境是:
<1>局域网. 所以写公网程序的兄弟就不要把公网的限制也考虑进来了.
<2>大型系统. 所谓的大型系统, 很难界定, 不过我就姑且人为地规定一个参考线: 平均每天1万以上的用户使用,100个以上的用户页面.  如果是小型系统, 只有几十几百个用户, 服务器轻松应付, 甚至web服务器根本和数据库服务器是同一台机子的情况, 就无需讨论了, 小型系统里可以说根本不用考虑性能问题, 只要不是自杀式代码, 都能满足要求.

本人曾先后就职于三家公司, 其中两家的员工数都超过了两万, 公司里有数百条生产线, 每条产线平均约10秒钟过一片产品, 每片产品都要刷条码, 而每条产线至少有十几站, 每站都要刷一下,  也就是说, 光是产线, 每秒都会产生至少几百个数据请求, 而如此庞大的公司, 同时在查报表, 走流程, 从采购->SQE->IQC->......->出货生管->客服 , 不知道有多少人在同时使用系统, 这还只是生产系统, 还有人事系统, 行政管理系统, 针对管理层的决策支持系统, 等等子系统,  -----其实凡是稍微了解一点大企业运作的兄弟肯定都知道这些, 这里为没接触过的朋友啰嗦几句.

这所有的应用中, 查报表是最慢的, 因为报表的需要是千奇百怪的, 有的报表纵深要汇总一个月,甚至几个月的数据, 横向要连接几十张表, 查询一次常常会需要超过一分钟, 而由于在这期间数据库忙于处理这个查询, 必然会延迟其它的请求, 这种交通堵塞效应在每月特定的时候(报表查询高峰) 会极其严重.  即使在平时, 系统的响应速度也几乎完全取决于数据库服务器的响应时间.

以上这么多, 只为了说明一点: 系统的响应时间99%由数据库服务器响应时间决定.  如果不同意这一结论, 就没什么可谈了, 因为我除了亲自工作过的三家公司外, 还听说,见过好几家大公司的情况, 都是这样的, 这是讨论下去的前提.

有了这个前提, 才有后面的结论, 必须尽一切可能减轻数据库服务器的工作量, 某一个报表查询时间如果能缩短0.5秒 , 那整体效应可能就是数分钟, 因为这一个查询早结束0.5秒, 其它的请求就可以早点被处理, 否则交通会越来越堵.

而大量包含业务逻辑的存储过程, 就是增大数据库服务器压力的元凶, 如果把一段50行的存储过程, 改成一个select 语句, 中间的差别多大, 我想不言自明. 

写到这里也就够了, 再写下去, 就又回去存储过程跟内嵌sql谁更好的怪圈了.

[2007/11/2 更新:]
我从来没有对自己的表达能力如此地自卑过, -----唉, 我看我有必要考虑是否要撞墙了.
wangyh 兄一针见血地指出了我关心的问题, 不是内嵌sql VS 存储过程, 而是SQL VS C#, 这才是关键.
xiaotie 兄的论断, 我并不同意, 不过我就不再做进一步的辩论, 因为我现在发现多说一句都可能使问题偏离中心. 既然他质疑我的"如果把一段50行的存储过程, 改成一个select 语句, 中间的差别多大, 我想不言自明. " 这句话, 我就把它改成, 把一段50行的存储过程, 改成只有一句的存储过程, 这应该没有问题了吧?

为了不使sp 派误会, 就假设程序中完全不出现sql 语句, 即使只有一句, 也写成存储过程, 但是, 这些存储过程都不包含逻辑处理, 而是都由C# 去负责, 也即我的标题, 存储过程是长枪, 内嵌sql 是短枪, 逻辑处理是自杀, 我现在不想讨论究竟谁更适合去做逻辑处理, 而是, sql 语言根本不要去做逻辑处理, 只要有可能用C#做的, 都用C#去做, 而不放在sql 语句中.

之所以会从这个讨论变成存储过程vs 内嵌sql, 原因在于, 当写存储过程的时候, 更可能会"不知不觉", "自然而然" 地把逻辑处理写进去, 而写嵌入式语句时, 更可能会把相应的处理用C# 实现. 

应该没有歧义了吧?

没有永恒的事
一切都在不断重复
我热爱这个世界
但绝不骄纵了它
posted on 2007-11-02 11:12 木刀 阅读(2496) 评论(47)  编辑 收藏 所属分类: asp.net 点滴

FeedBack:
#1楼  2007-11-02 11:27 future001 [未注册用户]
支持楼主!
  回复  引用    
#2楼  2007-11-02 11:31 Jeffrey Zhao      
有点不同意。我不觉得包含一定(原文是“大量”)业务逻辑的存储过程是服务器压力的元凶。存储过程的业务逻辑也要看是怎么写的,普通的IF...ELSE或者SET之类的不会有多大问题。
数据库压力是怎么来的呢?基本上都是因为“查询”带来的,所以对于查询的优化才是关键,而不是那些普通的业务逻辑。
而且如果存储过程中都只是查询的话,业务逻辑就必须在代码里出现了,于是反而可能就会因为增加了数据查询的连接次数造成性能的降低。
  回复  引用  查看    
#3楼  2007-11-02 11:44 邹健      
有一点不太明白:请教.
比如我 有一个对文章的操作,只有A类型的用户才能操作 但是曾经是A类型的用户也可以操作....
于是我是写
if(db.getBooleanbyProcedure("IsUserA")&&db.getBooleanbyProcedure("IsUserOldA"))
然后写操作...
这样将逻辑写在Web里...
还是直接写一个操作的存储过程....
if Exists(select ....A) or Exists(select ... old..... A)
这样呢,
因为我感觉如果是第一种方法....会重复连接数据库,相对来说对数据库也是一种压力,但第二种方法就少了这种压力,只是将业务逻辑留在了 Procedure中
....所以迷离中....
我想这也是楼主想要讨论的...
我个人倾向于第二种....
但觉得不可固步自封 ....
看看大家怎么看....
  回复  引用  查看    
#4楼 [楼主] 2007-11-02 11:44 木刀      
真是活见鬼了, 我只发布了一次, 不知道为什么会冒出来四篇, 这篇文章在草稿阶段待的时间比较长, 有几个小时, 莫非是这期间的自动存草稿的动作, 在最后都被发布了?
  回复  引用  查看    
#5楼  2007-11-02 11:50 袁永福      
楼主的观点有点意思。
  回复  引用  查看    
#6楼 [楼主] 2007-11-02 11:51 木刀      
@邹健
其实你的第一种方法封装程度很低了, 感觉区别不大, 经典的存储过程会把这个判断逻辑封装进去, 成为这样的形式:
if (ExecProcedure("IsHavePrivilege("userA")")) ......
而我更倾向于这样处理:
sql="select a.userName,b.userName from users a inner join oldUsers b on a.userId=b.userId" ;
ExecSql(...out dt...);
if(dt==null || dt.rows.count<1)......
  回复  引用  查看    
#7楼  2007-11-02 11:52 邹健      
@Jeffrey Zhao
赵兄又再现人间了...呵呵,好久不见...
  回复  引用  查看    
#8楼  2007-11-02 11:55 Clark Zheng      
继续跑来支持存储过程
  回复  引用  查看    
#9楼  2007-11-02 11:55 邹健      
@木刀
我感觉其实楼主和我们是想通过反复讨论...将原有的感性的安排与权衡,转化为一种公式与模式,找出最终的提高数据库效率方法
  回复  引用  查看    
#10楼 [楼主] 2007-11-02 11:59 木刀      
@Jeffrey Zhao
是的, 当然, 查询肯定是主要的部分, 问题在于, 这部分代价是不可避免的, 现在服务器压力沉重的条件下, 我的出发点是, 尽可能把一些不必要的东西抛开, 只留下这些最必要的. IF ELSE 什么的, 当然不会带来什么问题, 只不过, 在实践中, 我见过的存储过程大都很庞大, 动辄都近百行, 里面非查询的含量已经不少了, 对某一个存储过程来说, 当然, 它们的比例仍然很小, 但是, 存储过程太多, 执行的次数又频繁, 我想就不能再简单的忽略它们了.

至于连接的次数, .net framework 实际上会自动维护一个连接池, 在代码里关闭的连接, 实际上仍然是打开的, 下次仍然会使用它, 如果实在不放心的话, 可以自己在代码里再加一层连接池, 这样就可以确保连接不会被频繁地打开关闭了.
  回复  引用  查看    
#11楼 [楼主] 2007-11-02 12:02 木刀      
@Clark Zheng
:-)

@邹健
我觉得这主要是一种观念, 或者像"代码大全" 里说的, 是一种"隐喻", 而这种隐喻在很大程度上会左右写代码时的决定.
我自己怎么想都觉得这种观念是对的, 不过似乎确切地赞同我的人不多.
  回复  引用  查看    
#12楼  2007-11-02 12:10 邹健      
@木刀
是的....有时已经感觉自己得道了,其实可能还有更好的方法...
但直觉之上,有时有更理性的方法......

顺遍说个笑话....缓解一下心情...
上个月我对我写过的JS文件进行大批的重构.....重构中突然....将所有的"(双引)改为'(单引)了, 原因是我认为"是双字节...而'是单字节......汗....事后想来真是毛骨悚然...灵异事件
别人都说我当时让鬼给亲了....所以脑袋秀逗了....
  回复  引用  查看    
#13楼  2007-11-02 12:11 Jeffrey Zhao      
@木刀
连接池归连接池,但是您可以尝试一下,还是会有一定性能损耗的,因为毕竟还是RPC,而且每次连接的一些Audit、Login、Logout等操作总是不会省去。
其实怎么说,存储过程其实就是数据库对外的接口,存储过程里包含多少逻辑,还是要看这个接口是如何设计的,包含逻辑还是很常见的。
当然我一般也只放一些简单的逻辑,我不知道复杂的逻辑是什么样的……
  回复  引用  查看    
#14楼  2007-11-02 12:12 RicCC      
一些复杂、资源消耗比较大,而实时性要求不高的报表,可以每天、每周数据库比较空闲的时候,例如晚上、凌晨把数据跑出来,用户只是简单的查询结果
  回复  引用  查看    
#15楼 [楼主] 2007-11-02 12:16 木刀      
@Jeffrey Zhao
嗯, 是的, 如果调用存储过程只需要一次, 而提交sql 语句要好几次, 那肯定是不可取了, 现在暂且认为, 无论调用存储过程, 还是提交字符串, 都是只有一次, 或者说, 如果要多次提交, 则都需要多次, 公平起见么, 呵呵.

举个例子吧, 前天有个叫"简爱" 的, 也写了篇文章, 您好像也看过了吧, 他所写的那个分页的存储过程, 我认为就是反面的典型. 呵呵.

以下是我关于分页对他的回复:
@简爱
对于分页, 一般情况下, 能够预料到表中的数据有多少行, 如果行数不太多, 可以一次读出, 保存在session中, 这样换页的时候, 就直接从session 取数据就行了.

对于行数非常多的表, 采取更复杂的折中策略, 类似于缓冲策略, 假设表中有100万条记录, 先获取这个count, 让客户端知道一共有多少条, 然后读出一个固定的长度, 如5000条, 保存在session中, 如果用户请求5000条以后的, 再去读取相应的5000条, 一般情况下, 用户会顺序地请求数据, 所以直接取session就行了. -----实际上, 对如此大的表, 用户不太可能会请求所有的记录, 这种缓冲策略会极大的缓解数据库服务器的工作.

  回复  引用  查看    
#16楼  2007-11-02 12:27 RicCC      
不管用什么方式,加快每次db请求的处理速度,并且降低每次处理所需要的服务器资源,这是硬道理

你讲的复杂报表等,几十几百行的sql才能查出来,最好还是用存储过程,道理很简单,有利于数据库上的调优

使用存储过程,DBA可以充分发挥;放到程序中,程序员需要有DBA的能力,DBA可能不会管程序的东西,调优需要程序员进行,重新编译代码
优化策略很多,环境变化了优化策略也需要调整,例如3个表联合起来统计一个报表,其中某个表数据在5万、50万、500万等不同数据量上,sql语句写法以及其它各种配合的调优方法可能都需要用不同方式的
  回复  引用  查看    
#17楼  2007-11-02 13:42 DBer [未注册用户]
博主讲的情况,本人听闻甚多。
这里我不想评论什么,只跟据我看到的情形提些问题:

假如我们一直在记录世界上所有人的人种、血型、性别、年龄、身高、体重等等这些数据。而且我们已经统计出直到2007年11月1号为止,身高体重比最大的O型血男性黄种人。身高体重比只是我们打印在一张纸上用来娱乐大众的,所以并不会在数据库中存在这么一个字段。

问题来了,如果奥运会开幕那天,我们突然想知道到那天为止,榜单最上面那个人是谁。我们还是要把所有人的身高体重比再算一次吗?

再一个问题,某个鸟人突然想知道2006年4月1号那天,谁是这个榜首,又要重新计算吗?

虽然现实中许多统计问题是“相当复杂”D,但真的需要见人一张口就翻账本?而这恰恰是很多“吸血鬼式”的存储过程常有的特点。



  回复  引用    
#18楼  2007-11-02 14:04 Jeffrey Zhao      
@木刀
如果都只连接一次的话,那么直接上sql和存储过程其实只是发送的数据长度上sql略多了。
“简爱”的分页策略还是很常见的。其实类似的做法我也用过,不过我是通过传入的条件拼接字符串,然后sp_executesql + 参数的做法来执行。因为我的条件是查询条件会有很多,排序条件也有几个,究竟需要哪几个条件如何排序的组合无穷无尽,所以只能动态创建sql了
不过分页查询肯定是相对很耗资源,因此缓存也是不可少的,我的做法是根据参数(查询条件+排序条件+分页条件)的组合来缓存内容,并且定期地expire,效果还是不错的。
  回复  引用  查看    
#19楼  2007-11-02 15:13 SSSS [未注册用户]
http://www.cnblogs.com/cn_wpf/archive/2007/08/20/863022.html

评论了这么久,博主还是偏向于内嵌SQL

请问全国的证券后台交易系统需要什么样的性能,什么样的设计方式?难道还是内嵌SQL?

  回复  引用    
#20楼  2007-11-02 15:19 一支鱼刺      
刚学编程的时候,就学到一句名言叫:算法是程序的灵魂。

其实,算法写得好,用SQL语句也好,用存储过程好,都一样。
  回复  引用  查看    
#21楼  2007-11-02 15:22 A.Z* [未注册用户]
@SSSS
有可能是用c++写的sql
:P
  回复  引用    
#22楼  2007-11-02 15:25 SSSS [未注册用户]
--引用--------------------------------------------------
A.Z*: @SSSS
有可能是用c++写的sql
:P
--------------------------------------------------------
明确的告诉你,不是
  回复  引用    
#23楼  2007-11-02 15:31 Enzo      
算法是程序的灵魂,效率是程序的速度.
同意楼主的意见,多注重细微处优化,至于效果就不用多叙了
  回复  引用  查看    
#24楼  2007-11-02 15:55 Leisang [未注册用户]
其实。。。我比较倾向于增加服务器。。。
对我来说一个稳定的架构和方便的维护是最重要的,当然性能也是重要的,但没必要钻的太深,有时候用钱能解决的,何乐而不为呢。。。
  回复  引用    
#25楼  2007-11-02 15:57 Jeffrey Zhao      
@A.Z*
C++不适合写Sql,Sql是基于Set的操作,性能会高。
C++(2005里有clr intergration是类似的功能)适合写复杂,用sql处理比较麻烦的逻辑。
  回复  引用  查看    
#26楼  2007-11-02 16:01 xiaotie      
前面前提写的很不错,就是这句不敢苟同:

而大量包含业务逻辑的存储过程, 就是增大数据库服务器压力的元凶, 如果把一段50行的存储过程, 改成一个select 语句, 中间的差别多大, 我想不言自明.

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

几十上百行的存储过程,只要其中没有夸张的循环,业务逻辑部分所消耗的计算时间在微秒级甚至更低,这个时间和最简单的非内联函数调用是一个数量级的。即使在作者所述的那样庞大的应用中,仍可忽略不计。

相反,改写成select语句,哪怕就是有连接池,至少会在以下几个地方增加数据库服务器的负担:

(1)要多一些sql语句的解析负担。单是一个最简单sql语句的解析,恐怕其所耗时间就和一个复杂的存储过程中业务逻辑差不多

(2)增加网络传输负担.增加一个字节的网络传输所消耗的CPU资源和一行不含循环的普通代码差不多

因此,“大量包含业务逻辑的存储过程, 就是增大数据库服务器压力的元凶”这一句话是绝对绝对错误的,大量包含业务逻辑的存储过程执行过程中,数据库服务器所受压力大概可以分解为:

(A)接收并解析 sql 指令,这个时间粗略估计在10微秒-1微秒
(B)执行存储过程中的业务逻辑,如果不包含复杂的循环,这一时间在1微秒以下。对于简单的存储过程,这一时间在纳秒级
(C)数据的查询处理,一般在100微秒以上,长的话可以有若干秒
(D)数据的回发,这个时间是微秒级

平均下来的话,几者的比例 A:B:C:D = 30:1:1000+:10。

大量包含业务逻辑的存储过程是增大数据库服务器压力的元凶?
  回复  引用  查看    
#27楼  2007-11-02 16:07 Sleet [未注册用户]
同意楼上的
  回复  引用    
#28楼  2007-11-02 16:10 wangyh [未注册用户]
感觉有二:

1. 多次连接数据库发送sql/sp确实比一次慢,但是这个时间相比一条sql语句的执行时间并不占很大的比例。所以在这个地方优化无太大的意义。我觉得逻辑的清晰比这个重要很多。应该在程序写好后测试时碰到了性能问题再在此处找原因。

2. 几百行的存储过程并不一定就是不好的,关键是合不合理。 如果一个存储过程只包含一个目的,只执行一个算法,那我觉得就是没有问题的。另外有时把存储过程转换成逻辑代码,可以更好的优化,比如缓存一些比较小又常用的表。这个与sql vs sp没什么关系。 最重要的是这个算法用sql写很好还是用C#之类的语言写更好。
  回复  引用    
#29楼  2007-11-02 16:16 wangyh [未注册用户]
@xiaotie
平均下来的话,几者的比例 A:B:C:D = 30:1:1000+:10。
------------------------------------------------
很同意你的观点,但是这只是从技术的角度来讲。
我觉得从工程的角度来讲,"大量包含业务逻辑的存储过程“ 99%都是由sql水平并不很高的人来写的。不管是存储过程还是函数,这么多代码出错的几率是很高的,而且优化也很难。

或许确实有1%效率高,逻辑清晰的这种存储过程,但是其他的99%仍然是效率的瓶颈。

  回复  引用    
奇怪,怎么没有人针对楼主说的环境来讨论呢?
我就搂住说的这个环境来说一下我的看法吧

1、流水线上扫条码的地方应该使用存储过程,我的理解是没扫一遍就要记录到数据库里面,这样频繁的操作应该用存储过程,能够加快反应时间。
我想是存储过程的预编译发挥的作用吧。

2、置于查询嘛,最根本的方法是弄两个数据服务器。
A:正常操作。 B:专门用于查询。

就是说要查询的时候把数据从A复制到B,然后在B里面查询。

当然了,复制数据也是挺占用服务器的,但是解决方案就多了呀。另外对于A来说是只读状态。因该会比查询的负担小一些。

另外还可以根据实际情况在复制数据库方面想点其他的办法。

3、我感觉查询里有四个占用时间的阶段。

A、SQL查询数据
B、SQL提取数据
C、SQL把数据交给程序
D、程序绘制页面。

注意:对于Web来说,绘制表格也是很占用时间的,尤其数据大的时候。

  回复  引用  查看    
#31楼 [楼主] 2007-11-02 17:41 木刀      
@xiaotie
我不能同意你的观点, 不过也不再就这个问题再讨论下去了, 原来是我的话没说清楚, 我已经更新了主贴, 呵呵.

  回复  引用  查看    
公司里有数百条生产线, 每条产线平均约10秒钟过一片产品, 每片产品都要刷条码, 而每条产线至少有十几站, 每站都要刷一下, 也就是说, 光是产线, 每秒都会产生至少几百个数据请求

==================

根据 xiaotie 提出的数据我们来计算一下生产线的问题。

>>(A)接收并解析 sql 指令,这个时间粗略估计在10微秒-1微秒

我们折衷一下,按照 5微秒 计算,一秒钟产生200个数据请求。

在解析sql 指令的时候就需要1000微秒了。



  回复  引用  查看    
楼主你看一看标题,是不是也要改一下。
  回复  引用  查看    
#34楼  2007-11-02 19:05 徐少侠      
博主

尊敬你的学习精神,所以来讨论一下
我的结论是,你基本不了解数据库管理和调优。因此对存储过程的偏见有这么大

首先,从根本问题上讲你应该已经知道了存储过程是预编译的。
假定是两个完全一样的select语句,即使不考虑在程序里拼接SQL的时间耗费,在数据库引擎端那里,SQL字符串需要经过编译和执行两个步骤,而存储过程仅仅需要执行。
两者在执行速度上的区别是必然存在的,越是大型的,频繁的数据库,越斤斤计较这每次的0.000001秒

正如博主说的
而大量包含业务逻辑的存储过程, 就是增大数据库服务器压力的元凶, 如果把一段50行的存储过程, 改成一个select 语句, 中间的差别多大, 我想不言自明.

这个论据不能说明使用SELECT比存储过程性能更好,只说明写这个存储过程的人笨

例如按照既定的扣税规则,将雇员表的实发工资进行累进扣税,其实的确只要一条updata指令就能完成,如果我们去写存储过程,并且还要用到游标和循环。那么除了说写存储过程的人不懂怎么写SQL就没有什么好说的了。不能说存储过程慢

另外指出一个你没有发现的问题
在你的表达中:
这所有的应用中, 查报表是最慢的, 因为报表的需要是千奇百怪的, 有的报表纵深要汇总一个月,甚至几个月的数据, 横向要连接几十张表, 查询一次常常会需要超过一分钟, 而由于在这期间数据库忙于处理这个查询, 必然会延迟其它的请求, 这种交通堵塞效应在每月特定的时候(报表查询高峰) 会极其严重. 即使在平时, 系统的响应速度也几乎完全取决于数据库服务器的响应时间.

我告诉你标准的解决方案是什么
第一:
数据库都支持分区表技术,就是将一个表按特定规定拆分成几个我物理上独立的表。这样一来,如果按时间来分的话,那么就不需要每次对整个长达若干年的数据表进行扫描,可以节约大量的时间。
第二:
数据库创建的时候必须要一个数据文件和一个日志文件,但是数据文件并不是最多只有一个的。另外还有文件组的概念。
如果在创建数据库的时候,将预计可能会有大量数据且被频繁访问的表创建到由多个文件组成的文件组中,而这多个文件又被独立存放在单独IO通道的磁盘上。那么就如同磁盘阵列(RAID)的道理一样,读取速度呈N倍增长
第三:
如果经常有报表的功能,那么其实除了数据库范围内的联机事务处理技术以外,还有一个叫做联机分析处理。
简单说就是将历史数据从原始数据库中按周期提取并用多维数据集的方式存储到一个单独的数据库中。这么一来,对业务数据库的访问性能将基本不会受到对历史数据库进行报表查询的影响。

综上所述,数据库技术是一门博大的技术
博主既然已经意识到一个项目的性能99%是有数据库决定的,这个我绝对同意
那么就应该从发生问题的地方着手,在数据库范围内寻求可能的解决方案

最后再次提醒博主
一个写了50行的存储过程是有可能变成一个Select的
但是并不是每个存储过程都能变成一个Select的
在相同的SQL语句情况下,存储过程一定要比SQL字符串执行得快
哪怕只快0.00001

  回复  引用  查看    
#35楼  2007-11-02 20:59 邹健      
@徐少侠
学到很多知识....那分表时 我要怎么查询呢?进行连接? 一个服务器上好说,但如果在不同服务器上不同的数据库内呢,有没有相关解决方案的书或可以学习呢,希望推荐....
  回复  引用  查看    
如果表的索引建的合理,存储过程的执行速度要快的多,而且方便维护,至少我处理的几百万条数据没有出现过有超过1分钟的,消耗时间的其实那也是我的索引没有建好的原因。我的存储过程最少要在100行以上,所有的逻辑判断都在里面。呵呵,到现在还没有死人呢。
  回复  引用    
#37楼  2007-11-03 08:39 OK_008      
这问题讨论得有意思。
其实每一种模式都有自己的好坏两面性。
我们应该讨论的是怎么样发挥他们的优势才是真理,
而不是谈论他们的坏处,不使用他们。


  回复  引用  查看    
#38楼  2007-11-03 09:16 pbc1984 [未注册用户]
存储过程的临时表。游标等可以用DataSet,数组,循环等代替.
  回复  引用    
#39楼 [楼主] 2007-11-03 23:56 木刀      
@徐少侠
说句实在话,对你的评论很不满......你花了一半篇幅证明存储过程的效率高于sql语句, 难道我有在任何时候说过, 存储过程的效率低了么?

你的后一半篇幅跟我所讲的主题也没有任何关系, 不知道你为什么会以此为论据来批评我, -----我不是听不得批评, 只不过被批得有点莫名其妙, 呵呵.

"数据库是一门博大的技术", 这是当然, 由于涉及的东西太多, 所以不可能把"数据库" 当做话题来讨论, 否则会死人的. 在这里我只是想旗帜鲜明地反对很长的, 包含了业务逻辑的存储过程.
  回复  引用  查看    
#40楼  2007-11-04 20:52 亚历山大同志      
2日不见,居然又有了这么热烈的讨论,真实太高兴了。
首先,讨论存储过程还是嵌入Sql,需要分清楚场合。要看你的数据库是集中式的还是分布式的。根据网络拓扑来判断可能的瓶颈所在。
抛开是不是应该把包含业务逻辑的存储过程放在数据库的问题。
我们光从性能上来说,存储过程的问题在于大量占用了数据库服务器的计算资源。举个例子,某电信的网络计费系统在结账的时候,用了一台小型机,上面装了Oracle数据库,用了一个超大的存储过程来进行结账的操作,执行一次要跑好几个小时。博主也是在高并发大数据量的系统的环境下才会感觉到执行存储过程对数据库服务器所带来的负担。不过对于这类系统,我觉得无论是存储过程还是嵌入Sql都会有制约的瓶颈。其实用一台Oracle的TimeTen作为前端数据缓存对性能的提高才会有比较显著的改善。
  回复  引用  查看    
#41楼  2007-11-05 14:13 徐少侠      
--引用--------------------------------------------------
邹健: @徐少侠
学到很多知识....那分表时 我要怎么查询呢?进行连接? 一个服务器上好说,但如果在不同服务器上不同的数据库内呢,有没有相关解决方案的书或可以学习呢,希望推荐....
--------------------------------------------------------
一个设计良好的数据库,通过使用存储过程来暴露功能。在程序代码中根本不会感觉数据库的设计的不同。即使它其实是跨了服务器的。这一切都由数据库自己来管理。
因此,在进行查询时和平时写语句没有什么区别。即使是直接在代码中写语句,也 依然是类似Select * from Table1 where data between '2000-1-1' and '2003-12-31'
数据库的设计是和数据的使用必然关联的,有什么样的使用,并且因此造成性能损失,那么就需要DBA进行数据库性能分析并加以解决。
这个时候,如果是代码内嵌SQL。那么数据库的任何一个变更都足以使得软件修改至少若干天。还要回归测试若干天。
中国的程序员在讨论问题的时候老爱拿身边的例子。这个本来不错。
错就错在我们身边的例子都如同玩具一样。
没有多少人真正考虑大型项目的需求。没有多少人能理解Win操作系统是怎么弄出来的。

要学的话至少可以先看看SQL自带的联机帮助
能搞懂联机帮助50%,做一个DBA是没问题的了

  回复  引用  查看    
#42楼  2007-11-05 14:25 徐少侠      
@木刀
在你的文章中,体现的思想是仅仅将数据库做为简单的数据存储的位置。
数据库除了保存或返回数据,没有过多的功能了
你建议将业务逻辑尽量都放在代码中,这个自然不算大的分歧

我提了些批评
主要出于这写考虑
首先不要仅仅因为一点点的问题就否定存储过程的意义
第二,你拿来进行论证的例子其实即使使用再好的程序代码,如果没有正确地使用数据库技术进行解决,你也是解决不掉的。假设我们大家的项目的数据库都只有一个数据文件的话,那任何提升性能的方法即使能提升,也绝对是缘木求鱼。如果因此再去使用各种其他技术?好啊,有什么意思呢?

解决项目的性能问题,要看准问题的所在。

如果抛开任何环境,我坚持我的一个观点
只要语句一样,存储过程的执行就是要比发送SQL要快
因此,即使你使用若干语句,将人家的几十行的存储过程转变成了一个SQL加上你的程序代码
我只要将你最后那个SQL转变成存储过程。整体执行速度就一定比你的快

这两种方式其实仅仅是将压力从数据库服务器转移到了应用服务器。整体的系统压力还是在的。

因此,这种例子并不是证明存储过程或内嵌SQL哪个更好的准确的例子


  回复  引用  查看    
#43楼  2007-11-05 14:31 徐少侠      
--引用--------------------------------------------------
木刀: @徐少侠
在这里我只是想旗帜鲜明地反对很长的, 包含了业务逻辑的存储过程.
--------------------------------------------------------
这样哦

所以我觉得还是例子不好。

另外,报表服务就是数据库本身应该做的一件事情,绝不是什么其他的
SQL2005甚至已经将Report Service集成到了里面
联机数据分析服务也是已经历史悠久的商业决策依据

你的例子里面使用生成报表时候的计算过程会大大影响应用系统性能的问题,其实就是分析服务所应该完成的功能。

因此。我的后半段文章就是给你指出解决的方式。
  回复  引用  查看    
#44楼 [楼主] 2007-11-05 14:55 木刀      
@徐少侠
"这两种方式其实仅仅是将压力从数据库服务器转移到了应用服务器。整体的系统压力还是在的。" 呵呵, 这个是当然的, 我在这一问题上的观念是: 假设一个需求用数据库服务器来承担是10, 在应用服务器上是20, 也要移到应用服务器上去, 更何况, 实际上我认为在应用服务器上很可能会是5甚至更少.

我之所以说不满主要是你用太多篇幅来证明存储过程好, 似乎你没有认真看我的原贴, 呵呵, 我在原贴中花了不少笔墨来弄清我的立场, 我不想在这里讨论存储过程是不是好于sql语句, 因为我的前一篇已经大量的讨论过了, 并且有人批评说这种争论是"月经博", 每过几个月就会说一次, 让我很汗颜, -----不仅是我, 我想任何人也不会认为存储过程的效率低, 我个人的态度仍然是尽量地不用存储过程, 不过我并不想再继续讨论这一点, 我之所以不愿意用存储过程, 当然是因为其它原因, 而不是存储过程的效率低下.

关于数据库的使用程度, 这才是我关心的point, 如你所说, 我认为数据库只应承担存取数据的工作, 甚至可以说, 使用复杂的sql 语法, 或是数据库附带的其它非数据操作功能, 我觉得这些是"奇技淫巧", 不值得提倡使用. 原因很简单, 出发点仍然是尽一切可能为数据库减轻工作压力.

前面我也说过, 一个工作即使数据库更擅长, 只要有可能转嫁给应用服务器, 就毫不犹豫地转嫁给它, 即使这个工作要增加一倍的代价也在所不惜. 只让数据库做它最基本, 最擅长的工作, 它肯定会做得更快更好.
  回复  引用  查看    
#45楼  2007-11-05 15:41 徐少侠      
@木刀
我的观点是数据库其实还是很经得起折腾得
他有很多潜力没有被人挖掘出来

你的做法也一样会让应用服务器负荷日益增加

我可能理解你这么做的原因,因为我们都是程序员
能用程序来解决问题是我们最自然的想法

并且正如你说的,很多时候将压力转到应用服务器其实是会节约时间的。

因此,有你这样的结论就很自然的。

但是就如同谈论什么时候才需要OO一样。一个这里好的做法,不一定永远是好的
程序的分层,就是要让程序每层各司其职。互相降低耦合。

针对实际项目,只要合适的方法就是好的。

但是我们如果是讨论类似于应用JEE规模的项目。讨论理想和尽量通行的做法。
让应用层分担数据库的固有功能,那才算是小技巧呢。

在大型项目的持续维护中,数据库的表结构不会永远不变的。
数据库不会永远仅仅是一个数据库服务器的。
并且,这一切都可能在项目运行过程中发生变化并进行解决的。
这时候才是内嵌SQL的死穴。

你的做法,能够救项目于一时。不能救项目于一世

自然,我知道我国的99%的项目都是做的一锤子买卖
收钱,走人。
只要完成功能,今后的维护?谁管?
数据表太大了,要进行垂直拆分?内嵌SQL还能用吗?


  回复  引用  查看    
#46楼  2007-11-05 19:03 随心所欲      
讨论这么激烈.
基本同意博主的意见. 但是有些情况下,为了减少链接只能写一些存储过程,无可避免.

  回复  引用  查看    
#47楼  2007-11-12 13:17 cozo [未注册用户]
我知道移动公司做数据处理生成报表的时候,是把所有用到的数据复制到另一套数据库里去做的。
  回复  引用    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-11-02 17:39 编辑过
 
另存  打印