数据库访问的性能问题与瓶颈问题

声明

本文是一篇有争议的文章,甚至有可能是一篇争议非常大的文章,可能争来争去依然无法得到一个统一的意见。

场景

个别公司的技术决策者要求团队的开发人员在编写数据访问层的时候,禁止在程序中出现任何的SQL语句,禁止使用Entity Library,禁止使用NBear、NHibernate、IBatis、Entity Framework等ORM框架,只允许使用存储过程。试想一下,您的公司是否是这样子的?您的身边有没有这样的朋友,他们的公司存在这样或类似这样的情况吗?

矛盾点

cry 对于开发人员来说,使用存储过程的话,工作量比以前要大很多,而且涉及到表的字段更改,项目重构也是个非常麻烦的问题,使用ORM很方便就可以实现数据的CRUD功能,多表操作也非常的容易,原来写很少的代码就可以操作数据,现在却要写很多的代码。本来公司给的时间就短,项目紧,现在这么一搞,工作量一下就增加了不少,再者,如果需求一旦发生变化,不可避免的数据库就得增加或修改某些字段,相应的存储过程跟数据访问层的方法都得做调整,开发人员的日子不好过了。

smile 对于公司的决策者来说,性能问题是不可以妥协的,无论付出多大代价,既然做出了决定,那么就没什么好讨论的。

结果

结果可想而知,最终是按照决策者的决定,开发人员加班加点的做开发,既然决策者都已经做了决定,似乎再讨论用不用存储过程就是一个非常敏感的话题,再讨论类似的问题的话,开发人员所面临的处境就可能是尴尬的,在某些公司甚至是危险的。无论怎样,开发人员可能最终都很难改变决策者的决定。

决策者的心声

带着这些疑惑,我跟多位决策者进行沟通,搜集了他们的意见,总结下来的话,大概就是以下几点:

  1. 性能问题。经过测试,使用ORM比直接调用存储过程慢10倍。如果是做软件项目或软件产品,使用ORM问题不大,可是如果是以运营为主(访问量较大)的Web网站,性能上就会有问题。
  2. 并发问题。一旦访问量较大并且达到一定数量级的时候,ORM就可能会出现并发问题。
  3. DBA的能力受限。一旦出现性能问题,如果是按照写存储过程的方式来做,公司可以招来技术实力强的DBA直接改存储过程进行优化,而如果是使用ORM的话,那么DBA就很难进行优化,因为DBA很难读懂ORM写的程序,更不知道ORM内部的实现方式,这样一来,DBA的能力就得不到施展。
  4. 不愿意被微软绑架。以Entity Framework为例,Entity Framework不是开源的,如果出现性能问题,不能够看到源代码,这可能是一个风险。再者,一个强有力的公司强有力的团队,如果没有自己的技术,总是使用微软的不开源的框架,这怎么可以?
  5. Entity Framework是微软的产品,微软的产品只适合中小型的公司做开发,大的互联网公司是不敢用的,甚至他们可能采用Java+Oracle来做,一旦达到一定数量级,微软的东西就可能会出现问题。

笔者的心声

在充分理解了决策者的心声以后,我思绪万千,心中久久不能平静。终于,在把很多东西看淡,抛开杂念,在这样一个宁静的夜晚,也坦诚的把我的想法一一阐述,分别针对决策者的心声,谈一谈我的个人看法。

1.到底什么是性能问题?存在不存在性能问题?   
来看下测试是如何做的,使用存储过程进行插入或删除操作,分别使用存储过程和Entity Framework,循环10000次或者1000000次操作,然后整体上存储过程要比使用Entity Framework要快10倍。实际场景是怎样的呢?
实际的场景是用户点击页面上的按钮,执行了1次操作,我们假定按照写存储过程的方式来做,用户这1次操作可能需要0.001秒,而使用Entity Framework要慢10倍,用了0.01秒,那么这0.001秒比0.01秒的确是快10倍,但是对用户来说,可能根本就没有明显的差距,因为这么微弱的时间用户是体会不出来的。我们开发的程序,对用户来说,我们的产品会不会因为这0.001秒跟0.01秒的差距而打折扣呢?这微弱的差距是严重性能问题?还是可以忽略不计?

2.到底存在不存在并发问题?

诚然,可能之前有团队使用ORM开发高并发的项目,他们在运营中出现了并发问题,可是DBA又无法查出来到底是什么地方导致了并发问题,最终把一切的一切归咎在ORM上。

亲爱的朋友们,让我们理智的冷静的来分析下两者的技术实现上的不同吧。

直接调用存储过程:打开数据库连接--》执行编译好的数据库语句--》关闭数据库连接

ORM:打开数据库连接--》把对象解释成SQL语句--》执行SQL操作--》关闭数据库连接

通过比对我们可以发现,ORM就可以比作是一个SQL生成器,它把对象解释,拼一个SQL语句出来,然后在执行这个SQL语句,由于还需要解释,就相当于多了一步翻译的工作,因此,就比存储过程慢了一点点,那么慢的这一点点会不会出现并发问题?我的意见是并发问题多半是由于锁的影响,只要不产生锁,就不会有并发问题。正因为如此,高并发的项目开发,多半是忌讳使用事务,有的程序员手写异常后的数据库回滚语句(有些滑稽哈,但事实上就是这样),项目中也不推荐使用游标跟触发器。

3.DBA能力受限。诚然,DBA看不懂ORM写的程序,更加不明白ORM内部的实现原理。但是,DBA是可以跟程序员配合,利用SQLProfile等工具,看到最终SQL语句是如何执行的。也就是说,DBA的能力也是依然可以发挥出来的,只不过是需要跟程序员配合而已,或者DBA需要熟悉如何调试、跟踪。如果说全部写存储过程了,DBA能力是放开了,可是程序员的能力就受限了,譬如说,在进行大批量的数据插入的时候,大家都知道,.ADO.NET2.0的一个新特性SqlBulkCopy是多么的快,估计这是DBA无法优化的。对SqlBulkCopy不熟悉的朋友,请参考《SQLServer中批量插入数据方式的性能对比》。

很多时候,一个软件性能的优化,需要从整体去考虑,并不一定是说出现数据库性能问题,就一定是DBA的责任,或者说一定是程序员的责任。在DBA跟程序员之间难道就真的像插销跟插板之间那样,职责分的特别的清楚?很多时候我们得充分利用存储过程的特性,跟.NET平台的一些优良特性,选择适合我们的来进行开发,没有什么是最佳的,但是对我们来说,适合我们就好。

从另外的角度考虑,其实在项目初期,DBA就应该参与进来,进行数据库的设计了,而一旦数据库设计好了,设计得并不规范,存储过程也些了成千上万了,将来一旦出现性能问题,相信也够DBA喝一壶的。

4.不愿意被微软绑架。这个观点倒是让我感觉到意外,至少我们很多都在用微软的.NET Framework,我们使用微软的SQL Server数据库,如果说我们被绑架,可能现在就已经被绑架了,SQLServer的存储过程跟Oracle、Mysql的存储过程是不一样的,如果将来进行数据库的迁移,那么可想而知后果是怎样的。到底怎样才是真正的被绑架?

5..Net与Java孰好孰坏?

关于这个问题的讨论,一直就是个无休止的讨论。scottgu把这个比作是“带有宗教性质的技术争论”。诚然,讨论这样的问题的确令人讨厌,而且是浪费时间,而且讨论的双方都深切的关注着。讨论来讨论去最终也不会有结果。

在目前所运行的软件系统中,我们可以看到其背后的平台、语言等是各种各样,MySpace是基于.NET平台的,淘宝网是基于Java的,而Google则推崇使用Python,许多大型的电力系统还依然运行在C++平台上,最关键的一点,.NET并不是没有在大型项目中应用。只不过是Java起步早,.NET起步晚而已,要在前几年,Java做的大型项目的确是比.NET的大型项目要多。

很多时候,即使是使用相同的开发语言,不同的程序员开发的程序效率就差30倍以上,甚至几千倍以上,这点好不夸张。诚然,每门技术自有其缺点,但它们也都自有其优点,如果它的优点恰好能符合你的需要,用它就好了。重要的是,你有没有使用好它的能力。

总结

其实总结就不必了,说点题外话吧。存储过程在单条执行操作的时候,的确要比使用ORM要快,可是如果是执行批量的操作,使用存储过程就会非常的费劲。之前我是这样做的。假定更新1000条数据,数据库里只有2个字段,循环调用1000次存储过程需要2分钟左右,当时我把要更新的id以参数的形式逗号分隔传入存储过程,在存储过程中循环执行1000条数据,发现时间跟循环调用1000次存储过程的时间是差不太多的,最终进行了改进,改进的方法嘛,还是把要更新的Id以参数形式逗号分隔传入存储过程,然后使用update table set value=’value’ where id in select id in 分隔函数(id1,id2,id3…..),经过这种方式,更新1000条数据的时间从2分钟变成了200毫秒,可是问题依然不完美,方法存在局限性。

首先,使用这种方法参数的长度是有限制的,varchar类型最大不超过8000,nvarchar类型最大长度不超过4000.

其次,如果表中有多个列,要更新的也是多列,存储过程的局限性就出来了。

再次声明:文中观点仅代表个人观点,如果您有不同意见,欢迎共同讨论。

最后,给大家分享个幽默视频,来缓解下这种紧张而激烈的争论吧。

《办公室里有这样的女人你能安心工作吗?(中文字幕)》

作者: 深山老林
出处: http://wlb.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
9
0
(请您对文章做出评价)
« 上一篇: SQLServer中批量插入数据方式的性能对比
posted @ 2010-03-14 03:29 深山老林 阅读(1974) 评论(46)   编辑 收藏

 

   回复   引用   查看     
#1楼 2010-03-14 05:39 |        
似乎并发问题是对象产生并发错误。不一定是数据库事务。
使用了orm,有可能在内部实现机制上有一定的singleton 或者 static,如果设计不好,这里就会产生并发问题。然后抛出异常了。


其次是性能问题,使用了基于.net的orm,性能可能不止10倍这么简单了。可能相同的一次操作orm慢10倍,但是用户点击一个button,里面包含了orm10个操作,那么性能就慢了100倍。。这个也是我用orm到现在发现的问题。.net的反射实在太慢了。


不过至于说是否被微软绑架,难道使用存储过程就不被绑架?使用Oracle的存储过程能够无缝移植到SqlServer? 这点估计可以让绑架论的人们住嘴了。压根没有关系,这头逃离了微软,那头就投入到了oracle。

   回复   引用   查看     
#2楼 2010-03-14 05:42 |        

我个人觉得,使用ORM的场景,都是操作不平凡的场景。而这些场景又恰恰是整个业务的核心模型。就比如说网络购物,像购物车、用户这些对象完全可以用ORM,他们变化不平凡。

但是建立订单、入货单这些,绝对要使用数据表结构,如果用ORM,得不偿失。

所以看什么时候用吧。都是核武器,我一手一个同时开火,火力一定比单武器的强。

   回复   引用   查看     
#3楼 2010-03-14 06:01 | hiebc       
顶楼主。
反对辰 !
dal 是否选择orm我个人认为是可取的。

开发也是分阶段的。你在初期,业务复杂,但是访问量小。那么为什么不用orm呢?把焦点放到业务上面。用存储过程累死人。。稍微有点改动。。真的让人头痛。------就算访问量大,也不代表并发量大吧。。用mysql可以读写分离,或者使用memcached减少数据库的读操作。现在内存那么便宜。

你在dal层使用orm也不代表你以后就不能转到存储过程。在一些并发量大的地方,业务稳定了以后在dal层做一些改动也是可以的或者直接转到存储过程。

现在的企业,内部的那点小需求,小操作,有什么是orm搞不定的?现在花那么多的人死拼在存储过程干嘛?业务理解错误或者公司更改策略,带来的工作量是多少啊!!!还不如把那些精力放到用户体验上面。带来的效率视乎比你要死拼存储过程带来的效率高的多吧。

如果你公司是一个像facebook,sina那么高的用户的话。那么就不是简单的orm和存储过程了。需要注意的重点也就不同了。loadblance,cache,索引等等!而且也是一步一步改进过来的。谁能一步到位??

   回复   引用   查看     
#4楼 2010-03-14 07:53 | kiler       
引用辰:
其次是性能问题,使用了基于.net的orm,性能可能不止10倍这么简单了。可能相同的一次操作orm慢10倍,但是用户点击一个button,里面包含了orm10个操作,那么性能就慢了100倍。。这个也是我用orm到现在发现的问题。.net的反射实在太慢了。


现在用反射的orm貌似也不多了。
一次操作orm慢10倍那是极为特殊的情况(一般来说是使用不当造成的),不要把这个东西作为一个普遍的结论。
多个操作,orm还真不一定会慢多少,尤其是复杂的业务操作,在代码里面运行与数据库无关运算逻辑运算肯定比在存储过程里面写函数快。


我不反对使用存储过程,性能确实遇到瓶颈可以用,但是没有必要全部都用,高射炮打蚊子并不合算,有人说大型网站一定要用存储过程,因为性能要求高,大型网站也就是前台一些关键的页面访问量高,追求性能的话,这些页面甚至都不会直接访问数据库的(使用静态化页面的技术),实在不行的话就这一部分用存储过程就行了。

   回复   引用   查看     
#5楼 2010-03-14 07:56 | kiler       
总是有人拿sina说事,但是sina的首页是不会访问数据库的,不是谁点一下首页就直接连到数据库读数据的。
   回复   引用   查看     
#6楼 2010-03-14 09:07 | Robin Zhang       
ORM和SP本来就是实现DB访问的两种不同方式,ORM好处是灵活方面,编程效率高,扩展好,SP则是性能好,便于传统职能分工,知道两者的优缺点,因地制宜,一个项目,采用何种方式,需要讨论,需要德尔菲专家论断,而不能一棍子打死。拒绝任何一个都是不明智的短视行为。
   回复   引用   查看     
#7楼 2010-03-14 09:25 | hiebc       
@kiler
是说我拿sina说事??
如果是,那我请你看清楚后,稍微思考一下然后再说话。

这些页面甚至都不会直接访问数据库的(使用静态化页面的技术),实在不行的话就这一部分用存储过程就行了。这里是不可能使用静态化页面的,更不可能用存储过程,使用静态化有可能造成IO瓶颈,而且如果有新的信息发布后再次重新静态化页面?它应该是使用cache。

当然,我也不知道它是否使用的了静态化,如果是我,我肯定不会用。我只是说首页。

   回复   引用   查看     
#8楼 2010-03-14 09:33 | 徐少侠       
同意大部分的楼主观点

但是楼主的核心矛盾是一个伪命题

对于开发人员来说,使用存储过程的话,工作量比以前要大很多,而且涉及到表的字段更改,项目重构也是个非常麻烦的问题,使用ORM很方便就可以实现数据的CRUD功能,多表操作也非常的容易,原来写很少的代码就可以操作数据,现在却要写很多的代码。本来公司给的时间就短,项目紧,现在这么一搞,工作量一下就增加了不少,再者,如果需求一旦发生变化,不可避免的数据库就得增加或修改某些字段,相应的存储过程跟数据访问层的方法都得做调整,开发人员的日子不好过了。

关键是楼主只是一个程序员,不是一个数据库方面的专家
至少不懂得如何在数据库领域进行编程的模式

使用存储过程本身就是隔离表字段更改对项目代码更改的一种手段
不能想象当不使用存储过程而直接使用SQL 或 ORM产品的时候,当数据库表字段必须更改的时候该怎么办?
前提是不允许重新生成数据库,仅仅是改个名字
更复杂的增加字段,拆分表、合并等等,对于ORM来说很多人95%以上的人更本不知道怎么去应对

使用ORM的人多数只知道重新映射一下,更本不关心数据库内部应该怎么样

至于使用了SP造成本来很少的代码变成很多,请举个例子
我知道一种多表操作的情况,就是在Java那里有种做法就是多表级联查询的时候是自己用代码一层一层来获取结果,自然就比直接一个多Join的语句要麻烦
但是这个明显是Java那里这些人对数据库操作极其性能不熟悉的结果

总之,我们多数的程序员仅仅是个程序员,都非常数据自己的代码世界
愿意用任何代码世界里的解决方案来解决问题

而数据库,这个有着强大功能的东西,在ORMer的眼里,只要能高性能完成CRUD就完全足够了
什么视图、存储过程、触发器、数据库物理设计
统统都可以忽视的

本质上,一个有经验的“高级”程序员应该了解代码世界和数据库世界整合后的整体解决方案

当然,硬性偏向任何一个方向都是走极端,都是不合理的

即使在大型、大数据量的项目中,不是每个模块、操作都面临超大规模的业务量。因此在性能和效率当中寻找平衡是需要点艺术感觉的


   回复   引用   查看     
#9楼 2010-03-14 09:33 | kiler       
我没说你,我只是说有些人动不动就拿出sina,fackbook的例子,证明做网站一定要用存储过程。
   回复   引用   查看     
#10楼 2010-03-14 09:37 | 徐少侠       
其实只要总结一下最极端情况下的场景就能了解不少了

当需求发生变化,要求数据库字段甚至表数量发生变化的时候

用ORM方式和传统SP的方式各自应该怎么应对
对项目现有代码的影响各自有多大?

其实,深入考虑下去就能发现很多平时讨论的话题,比如MVC,比如OO,比如设计模式都会在里面出现

对代码影响最大的的结果,就是没有应用这些技术的项目,而不是用不用存储过程

   回复   引用   查看     
#11楼 2010-03-14 09:48 | Keep Walking       
如果项目简单,没有啥访问量,比如没有达到每日50W的pv,完全没必要架构得的特别复杂,使用代码生成器,orm,完全没有性能问题。而且人员配置也没有专门配置一个dBA。
项目设计目标就很大,那就要考虑很多问题了,不是仅仅考虑这些。一些非常耗性能的地方,经常执行的地方,就需要很好的性能要求,一定需要使用proc,而且要精心调优,精心缓存。但是大站点也有些执行非常少的小项目,可以搭配使用orm,不过有一点注意的是这些orm的语句也需要精心调优,不然会拖慢整个数据库,比如一个全表扫描,或者带共享锁的非即时查询,都会拖慢其他正在飞速执行的紧急任务。
orm所消耗的那么点点资源,相比精心调优好你的数据库,要小得多,所以建议如果你正在使用orm而又嫌弃速度慢的话,还是先去精心调优你的数据库,而不是改大框架。

   回复   引用   查看     
#12楼 2010-03-14 09:49 | Cheney Shue       
最近在用Oracle的一套持久化构架方案,这个构架不光是orm而已,它可以缓存数据,而且有事务控制机制,就像内存数据库一样。在通过多个页面完成一个事务的时候,可以解决传值问题,或者是频繁访问数据库。
它的实例是有隔绝机制,一个共享实例可以相应很多的并发请求,缓存的使用率就很高。如果一个独立实例执行了数据更新的操作,它会把数据同步到其他实例的缓存。
还有池技术,除了自身的实例池,还有数据库连接池。避免每次的数据请求都需要建立数据库连接。

实际测试过,单独的请求,使用这套持构架初次响应时间会增加30%左右;但在并发的连续事务操作时,整体性能提升了60%多。

   回复   引用   查看     
#13楼 2010-03-14 09:56 | Keep Walking       
徐少侠说的很对,哪个合适用哪个,不是每个项目都能给你配一个DBA,不是每个项目都需要高性能,项目总需要时间,金钱的衡量,如果你的视野够开阔,不应该老把数据库看作别人的事,把它和程序作为一个整体,好好满足你的设计目标就够了。

另外orm有点不能满足的是存储过程可以绑定多个逻辑在里面,如果使用orm就得在程序和DB间交互几次才可以,这个跨进程的交互是非常耗费资源的。
而且使用.net事务和DB内部事务,当然是DB内部的效率要好。

   回复   引用   查看     
#14楼 2010-03-14 09:57 | kiler       
@徐少侠:
引用
不能想象当不使用存储过程而直接使用SQL 或 ORM产品的时候,当数据库表字段必须更改的时候该怎么办?

代码生成,用数据库更新实体类代码和映射文件,如果是改字段的话最多调用的业务层代码做点小调整,就是这么简单。
引用
更复杂的增加字段,拆分表、合并等等,对于ORM来说很多人95%以上的人更本不知道怎么去应对

还是重新生成,没什么大不了的,反倒是全用了存储过程以后,别说改个表,字段重命名都够你受的。
引用
至于使用了SP造成本来很少的代码变成很多,请举个例子

SP里面处理字符串操作(split),日期处理(日期解析),数字计算会比在程序里面写容易?
存数过程实现一个split多麻烦啊
http://www.cnblogs.com/chandler/articles/284291.html
SP处理事物能比orm处理事物简单?
引用
而数据库,这个有着强大功能的东西,在ORMer的眼里,只要能高性能完成CRUD就完全足够了

拿菜鸟程序员用orm和资深程序员写存储过程比较,你可以的,ORMer不懂db,谁告诉你的,不要拿片面做全面。

   回复   引用   查看     
#15楼 2010-03-14 10:00 | Keep Walking       
这么热闹,看来大雪让大家都窝家里啊,呵呵
   回复   引用   查看     
#16楼 2010-03-14 10:02 | kiler       
引用Keep Walking:
另外orm有点不能满足的是存储过程可以绑定多个逻辑在里面,如果使用orm就得在程序和DB间交互几次才可以,这个跨进程的交互是非常耗费资源的。
引用
如果多次交互用的是同一个数据库连接的,性能损失并不大,只要不多次打开数据库连接就可以了。说到底还是还是一个orm用得好不好的问题。

   回复   引用   查看     
#17楼 2010-03-14 10:08 | nzperfect       
还是看访问量吧,以前在某公司做开发,程序里是不能使用T-sql的,全部proc. 过大的数据量及复杂的业务,使用程序来处理,得交互太多次了。而且不便于dba调校。
在一个高档的服务器上,32 cpu 32G内存 ibm存储 全部使用proc,速度都得不到理想的效果,用orm那样的,基本就查不出来数据了。。。

   回复   引用   查看     
#18楼 2010-03-14 10:09 | hiebc       
@kiler
引用kiler:
@徐少侠:
引用
更复杂的增加字段,拆分表、合并等等,对于ORM来说很多人95%以上的人更本不知道怎么去应对

还是重新生成,没什么大不了的,反倒是全用了存储过程以后,别说改个表,字段重命名都够你受的。

可能你没理解他的意思!其实一点都不简单。如果你是豆瓣的一张大表有几千万行的数据,你怎么添加拆,合并。一个小的改动就可能锁表几个小时。这个豆瓣是不可能容忍的。 这个一点都不简单。

现在豆瓣新添加一个索引的解决方案是:一个新表,这个新表从旧表同步数据,然后再写数据的时候,也会同步,往两边写,一直到两边完全一样了,再把旧表删掉,大概是这样一个方式。

   回复   引用   查看     
#19楼 2010-03-14 10:13 | nzperfect       
数据量小,访问少,无所谓。
数据量大,高访问量,那么还要看来务复杂度,复杂度低,表数据交互少,其实ORM也可以接受,这需要一个好的架构师来抉择。

做为DBA来讲,是肯定希望用proc的。做为sql server来讲,它也希望用proc.

   回复   引用   查看     
#20楼 2010-03-14 10:14 | kiler       
引用hiebc:
@kiler
引用kiler:
@徐少侠:
引用
更复杂的增加字段,拆分表、合并等等,对于ORM来说很多人95%以上的人更本不知道怎么去应对

还是重新生成,没什么大不了的,反倒是全用了存储过程以后,别说改个表,字段重命名都够你受的。

可能你没理解他的意思!其实一点都不简单。如果你是豆瓣的一张大表有几千万行的数据,你怎么添加拆,合并。一个小的改动就可能锁表几个小时。这个豆瓣是不可能容忍的。 这个一点都不简单。

现在豆瓣新添加一个索引的解决方案是:一个新表,这个新表从旧表同步数据,然后再写数据的时候,也会同步,往两边写,一直到两边完全一样了,再把旧表删掉,大概是这样一个方式。



这个问题和是否使用存储过程还是Orm关系不大,这是纯粹的数据库维护工作。

   回复   引用   查看     
#21楼 2010-03-14 10:17 | nzperfect       
引用hiebc:
@kiler
引用kiler:
@徐少侠:
引用
更复杂的增加字段,拆分表、合并等等,对于ORM来说很多人95%以上的人更本不知道怎么去应对

还是重新生成,没什么大不了的,反倒是全用了存储过程以后,别说改个表,字段重命名都够你受的。

可能你没理解他的意思!其实一点都不简单。如果你是豆瓣的一张大表有几千万行的数据,你怎么添加拆,合并。一个小的改动就可能锁表几个小时。这个豆瓣是不可能容忍的。 这个一点都不简单。

现在豆瓣新添加一个索引的解决方案是:一个新表,这个新表从旧表同步数据,然后再写数据的时候,也会同步,往两边写,一直到两边完全一样了,再把旧表删掉,大概是这样一个方式。


企业版支持online=on选项,可以尝试。

   回复   引用   查看     
#22楼 2010-03-14 10:26 | kiler       
引用nzperfect:
还是看访问量吧,以前在某公司做开发,程序里是不能使用T-sql的,全部proc. 过大的数据量及复杂的业务,使用程序来处理,得交互太多次了。而且不便于dba调校。
在一个高档的服务器上,32 cpu 32G内存 ibm存储 全部使用proc,速度都得不到理想的效果,用orm那样的,基本就查不出来数据了。。。

过大的数据量及复杂的业务用proc处理未必会慢,proc操作数据是快,但是proc处理业务逻辑的能力比较弱(处理字符串操作,日期处理(日期解析),数字计算,循环算法),最终运行速度并一定快。这个东西说白了快不快更多的还是要看使用者对那个技术更熟悉。

我举一个很简单的例子,数据库处理树状结构,我在程序里面写一个Tree的类,一次读出所有的数据加载到Tree里面(一条sql),什么都搞定了,数据库存储也简单就一个parentID字段就可以实现,在数据库处理,那就麻烦了,要加上辅助字段,添加删除更新数据的时候还要更新辅助字段,查出树的时候要使用很多特殊条件,可能要多次查询数据库。

   回复   引用   查看     
#23楼 2010-03-14 10:40 | nzperfect       
不想做过多评论,正如这篇文章的开头声明。
因为每个人都是站在自己经历过的事情来做来评论的。

   回复   引用   查看     
#24楼 2010-03-14 10:56 | 韦恩卑鄙 v-zhewg @waynebaby       
参加过一个2000表20000存储过程的项目 全都用存储过程 而且是sql 2000 xml输出的存储过程 存储过程之间的调用达8层 在存储过程中为了实现分页等功能 采取了拼接sql 后运行的方式

这样的教条下 不得已做出来的产品 就算对dba来说都是一种煎熬 谁说sql期盼sp dba期盼sp我就笑笑

   回复   引用   查看     
#25楼 2010-03-14 10:57 | 韦恩卑鄙 v-zhewg @waynebaby       
顺便请教下 哪里有nb到不允许用sp的orm 我倒想见识下
   回复   引用   查看     
#26楼 2010-03-14 11:38 | 烙馅饼喽       
写个存储过程生成器。。。。反正这些都是重复劳动,有代码生成器,同样也可以有存储过程生成器。
   回复   引用   查看     
#27楼 2010-03-14 11:43 | 烙馅饼喽       
和决策那帮半瓶子水还自以为很了不起的家伙讲道理那是讲不通的,只有另外想省力的办法。增删查改全用存储过程?没问题,来个自动生成器不就OK了。顺便连注释都给他生成好!
我以前还干过这事情:我原来公司要求写日报,我就搞了个日报生成器,用一个服务监视工作目录,定时提取 .vb文件的改动,把代码注释填充进日报模版.谁高兴手写日报?有这时间我不会打会游戏睡会觉啊???有时候想起来就想抽那帮管理人员

   回复   引用   查看     
#28楼 2010-03-14 12:05 | killkill       
小压力,怎么玩都行。
ORM产生的SQL语句是否可以调整这个是比较头痛的。

   回复   引用   查看     
#29楼 2010-03-14 12:07 | W.SiMin       
代码生成器为主,ORM为辅,我就是这么做的
   回复   引用   查看     
#30楼 2010-03-14 12:09 | kiler       
引用killkill:
小压力,怎么玩都行。
ORM产生的SQL语句是否可以调整这个是比较头痛的。


没有必要调整,知道大概会怎么输出就行了,性能不好就换sql查,orm解决不了所有的问题。

   回复   引用   查看     
#31楼 2010-03-14 12:09 | W.SiMin       
ORM对批量修改比较有问题,我一般只用来查询,数据库操作就全用存储过程
   回复   引用   查看     
#32楼 2010-03-14 12:50 | kkun       
视频很经典哪!没法干活了,NG
   回复   引用   查看     
#33楼 2010-03-14 12:55 | Ivony...       
其实都是伪命题。。。。。


造成这种问题的根本是决策者不学无术,所以在我看来其实很扯淡。


先逐一谈谈为什么都是伪命题:

1.性能问题。经过测试,使用ORM比直接调用存储过程慢10倍。如果是做软件项目或软件产品,使用ORM问题不大,可是如果是以运营为主(访问量较大)的Web网站,性能上就会有问题。

这种决策者,真是相当的扯淡,运行效率固然重要,但开发效率也同样重要,同样的,质量、可维护性都是必须综合考虑的因素,如果只考虑性能问题,为什么不用ISAPI?为什么不考虑本地缓存,扯淡的很。。。。


2.并发问题。一旦访问量较大并且达到一定数量级的时候,ORM就可能会出现并发问题。

一旦访问量较大达到一定的数量级的时候,你把Oracle的CTO找来当DBA都解决不了问题。
任何东西都有极限,而线性的提高吞吐量是绝对无助于解决问题的。吞吐量需要指数级的增长,而这,绝对不是什么不用ORM可以搞定的。


3.DBA的能力受限。一旦出现性能问题,如果是按照写存储过程的方式来做,公司可以招来技术实力强的DBA直接改存储过程进行优化,而如果是使用ORM的话,那么DBA就很难进行优化,因为DBA很难读懂ORM写的程序,更不知道ORM内部的实现方式,这样一来,DBA的能力就得不到施展。

事实上DBA最痛恨的就是这种乱七八糟的存储过程不知道在干什么。技术实力很强的DBA都知道治本的办法是优化数据结构和增强缓存策略,而不是去抠SQL语句,一个业务发展速度中等的公司,平均每个月都要新增十几条SQL语句,要多少DBA才够?


4.不愿意被微软绑架。以Entity Framework为例,Entity Framework不是开源的,如果出现性能问题,不能够看到源代码,这可能是一个风险。再者,一个强有力的公司强有力的团队,如果没有自己的技术,总是使用微软的不开源的框架,这怎么可以?

哈,我倒还真没见过什么公司用开源数据库的。那SQL Server出了问题怎么办?!风险岂不更大。




那么问题到底出在哪里了?

的确很多公司程序员连最基本的关系型数据库的工作原理都不了解,写代码的时候完全不考虑数据库承受能力。数据结构一塌糊涂,还说是满足了什么一二三范式。

程序与数据库的割裂,程序员只管实现功能,不考虑数据库效能,而程序员的单元测试也很难反应性能问题,这是根本的问题。当然最好的解决方案是有一套完美的框架,可以使得程序员完全按照自己的意图写程序,框架会根据实际情况自动产生最完美的数据库访问指令。可惜这种框架还没有被发明。

在这种情况下,将教条死套到程序员的头上,成为了避免上头说自己不作为的一种有效手段。最关键的是,大家都这么弄的,当老板责问过来的时候,一方面可以表示自己还是有所作为(教条),一方面也可以辩称大家都这样,没有更好的解决方案。才是这些所谓决策者的真正心声。。。。


总结:

其实就是所谓决策者掩饰自己无能照搬教条的结果,就像不学无术的教授,在授课时除了照搬书本还能做什么呢?

   回复   引用   查看     
#34楼 2010-03-14 13:23 | 上不了岸的鱼       
呵呵,发现一个问题,很多人都认为varchar最大为8000个字符,nvarchar最大为4000个字符.
实际上并不是这样的,MSDN是这样说的:

[b]nvarchar [ ( n | max ) ]

可变长度 Unicode 字符数据。n 值在 1 到 4,000 之间(含)。max 指示最大存储大小为 2^31-1 字节。[/b]

也就是说nvarchar(max)最大可以存储2GB字节的长度.

MSDN链接:
http://msdn.microsoft.com/zh-cn/library/ms186939(SQL.90).aspx

   回复   引用   查看     
#35楼 2010-03-14 13:31 | Ivony...       
引用上不了岸的鱼:
呵呵,发现一个问题,很多人都认为varchar最大为8000个字符,nvarchar最大为4000个字符.
实际上并不是这样的,MSDN是这样说的:

[b]nvarchar [ ( n | max ) ]

可变长度 Unicode 字符数据。n 值在 1 到 4,000 之间(含)。max 指示最大存储大小为 2^31-1 字节。[/b]

也就是说nvarchar(max)最大可以存储2GB字节的长度.

MSDN链接:
http://msdn.microsoft.com/zh-cn/library/ms186939(SQL.90).aspx



nvarchar( max )是后来加的,应该SQL Server 2000就不支持。

   回复   引用   查看     
#36楼 2010-03-14 13:56 | Teddy's Knowledge Base       
“对于开发人员来说,使用存储过程的话,工作量比以前要大很多,而且涉及到表的字段更改,项目重构也是个非常麻烦的问题,使用ORM很方便就可以实现数据的 CRUD功能”

-对一个成熟的开发团队来说,无论是代码里写SQL,ORM,还是是写存储过程,基本的CRUD都可以用代码生成的,特殊的查询则orm和存储过程没有太大的effort差异,一点点改动就忙死程序员,只能说明开发团队不成熟,和“orm还是存储过程孰优孰劣”,并没有必然联系。

“性能问题。经过测试,使用 ORM比直接调用存储过程慢10倍。如果是做软件项目或软件产品,使用ORM问题不大,可是如果是以运营为主(访问量较大)的Web网站,性能上就会有问题。”
“并发问题。一旦访问量较大并且达到一定数量级的时候,ORM就可能会出现并发问题。”

-如Ivony所说,这两个的确是个伪命题,系统整体的性能,不能只是孤立地看sql或orm和存储过程的执行速度,实际上,性能调优的一般原则是“越上层的调优越便宜,效果越明显”,如果到了已经只能依赖于最底层的数据库层面的调优了(DB Review没做到位导致的sql低级错误和报表类的查询除外),说明整个系统各个层面的设计,需要好好反思了。当然,现实中,一方面很多公司的架构师不一定有驾驭整个系统性能的能力,很多性能问题不得已被集中到了数据库端;另一方面,很多公司对代码的管理,尤其是code review和DB review做得不够,或者现有的资源下没有条件做好,导致在代码层面不能约束程序员,逼不得已,只能通过代码中限制sql或orm,只允许存储过程来将和数据库查询相关的代码,尽可能集中到数据库端,“招来技术实力强的DBA直接改存储过程进行优化”。

“不愿意被微软绑架”

-这个就更是伪命题了。一个好的系统架构自然是不应该过于依赖于有风险的组件,即使是Entity Framework这样出自微软的组件。但是,降低依赖的副作用,是可以在架构设计上解决的。我们在架构设计时之所以要将业务层和数据访问层分离,就是为了让业务不依赖于具体的数据访问层实现。比如,我的大多数代码可以用orm快速实现,如果有一些对性能较高的功能,则完全可以用存促过程或其他策略进行重写优化,但无论怎么优化,业务层都应该是稳定的。所以所谓被微软绑架的担心,直接体现的是架构师的基本能力问题。


虽然我的身份也只是程序员,不是决策者,但对于决策者的过度批评我觉得也不公平。除去一小部分的确是能力问题的决策者,我愿意相信大多数决策者其实还是尽可能的希望在有限资源条件下,实现最好的性能的。无论是,限制必须写存储过程,还是其他一些孤立来看未必正确的决定,也许,从他的角度,已经是现有条件下最好的策略了;或者至少是愿意为了这个目标而改变的。那么与其抱怨,不如告诉他你好的建议。我们不可能强求每个公司每个团队每个架构师程序员DBA都那么成熟,只能尽自己的能力,尽可能让自己和身边更多的人正确的做事,不是吗?

   回复   引用   查看     
#37楼 2010-03-14 14:30 | 韦恩卑鄙 v-zhewg @waynebaby       
引用Ivony...:
引用上不了岸的鱼:
呵呵,发现一个问题,很多人都认为varchar最大为8000个字符,nvarchar最大为4000个字符.
实际上并不是这样的,MSDN是这样说的:

[b]nvarchar [ ( n | max ) ]

可变长度 Unicode 字符数据。n 值在 1 到 4,000 之间(含)。max 指示最大存储大小为 2^31-1 字节。[/b]

也就是说nvarchar(max)最大可以存储2GB字节的长度.

MSDN链接:
http://msdn.microsoft.com/zh-cn/library/ms186939(SQL.90).aspx



nvarchar( max )是后来加的,应该SQL Server 2000就不支持。

2005加的 而且性能逼近ntext 负面意义上的逼近

   回复   引用   查看     
#38楼 2010-03-14 14:46 | Alvin       
具体应用要看场景,楼主立论就是为了反驳,可以认为是一篇牢骚文!
唯技术论是我等程序员的通病,要改改这个强迫性思维,尝试中。。。

   回复   引用   查看     
#39楼 2010-03-14 14:52 | City22       
吵的真激烈。不过好像都是学术讨论啊,有几个人做过所谓的高并发的系统呢?
   回复   引用   查看     
#40楼 2010-03-14 15:19 | Jeffrey Zhao       
就是在扯淡,乱七八糟的理由
1、性能只和最终执行的SQL有关,ORM和手动的SP里SQL一样,性能差10倍是哪里来的?
2、反射慢?现在还有哪个ORM还用纯反射不用Reflection.Emit?
3、其他更都是扯淡或非技术问题了。
吵来吵去都是05、06年一样的话题了,理由还都是5年前的。
所以就算再吵,再得出什么结论,该不听的人还是不听。

   回复   引用   查看     
#41楼 2010-03-14 16:04 | Ivony...       
引用Teddy's Knowledge Base:
虽然我的身份也只是程序员,不是决策者,但对于决策者的过度批评我觉得也不公平。除去一小部分的确是能力问题的决策者,我愿意相信大多数决策者其实还是尽可能的希望在有限资源条件下,实现最好的性能的。无论是,限制必须写存储过程,还是其他一些孤立来看未必正确的决定,也许,从他的角度,已经是现有条件下最好的策略了;或者至少是愿意为了这个目标而改变的。那么与其抱怨,不如告诉他你好的建议。我们不可能强求每个公司每个团队每个架构师程序员DBA都那么成熟,只能尽自己的能力,尽可能让自己和身边更多的人正确的做事,不是吗?


我觉得这是一个看问题角度的问题,老实说我就不认同倪萍委员的如下言论:
“就党和国家的利益,在目前这个阶段,要是你想不出比它更高的招,你就应该拥护。(在投票时)我是考虑国家利益的,我热爱这个国家,我没有打断过,也没有弃权过。”


作为公民代表,我们政治水平不高,管理能力不强,只能发现问题而不能解决问题这是非常正常的。而政府部门拿着我们的税收,请了最优秀的科学家,他们不能解决问题那就是他们的责任,而不能说把责任再推给人民。


同样的,作为架构师或者DBA解决不了这种问题就是“无能”,就是“不称职”。这并不是说他们就该下岗,而是每个人都应该意识到这个问题的存在,而不是以你(我)也解决不了来搪塞。如果作为管理者不能解决更多的问题,那多拿的薪水就是不公平的。

   回复   引用   查看     
#42楼 2010-03-14 20:01 | 吉日嘎拉>不仅权限设计       
很少仔细认真看满篇都是文字的文章,我仔细看了,你写得很好,很多事情也都写明白了,阐述明白了。


   回复   引用   查看     
#43楼 2010-03-14 21:16 | Teddy's Knowledge Base       
@Ivony...
这个社会不公平无处不在,我们每个人只有做好自己是能保证的。作为一个人民的代表,倪萍的话的确不负责任的,不称职的,应该被人民批评的。“解决不了问题的架构师或者DBA”也的确是不称职的。不过,作为一个普通百姓,或者作为一个不称职者的同事,抱怨不公平自然无可厚非,但是,如果我作为一个公民还是愿意对我的国家负责,作为一个员工,愿意对公司付给我的薪水负责的话,做到自己应尽的义务就好了。我不懂统治者的政治,也不是我的老板,站在管理者的角度,也许,这些不称职者已经目前所能找到的最称职的人了也说不准。如果我有能力打到一切黑暗,维护世界和平,我也愿意义不容辞的去尽自己的义务。

   回复   引用   查看     
#44楼 2010-03-14 23:36 | 邀月       
这个不可一概而论,项目经理跟业主、老板的相互理解是关键!一个产品的业务性要超过技术本身!项目则很难说。
   回复   引用   查看     
#45楼 2010-03-15 00:53 | 活雷锋       
文章写的不错 个人感觉评论更精彩~
整个程序跑SP 团队开发中我个人认为是很恐怖的,
1.程序员水平不一样 如果你在存储过程中拼接SQL 然后excu那么效率并没有优势
2.团队开发 程序跟新相当麻烦 一个小小的操作也写一个PRO
简单的crud造成SP爆发 团队有老人走 或者新人进来的时候 相信如果是使用的一个清晰的ORM 接手会比SP快的多
3.对比 性能上的损失 和 开发时间 可维护性 做利弊权衡
ORM+适当的SP 无疑是很好的开发方式

   回复   引用   查看     
#46楼 2010-03-15 09:04 | 麒麟       
本人的代码生成器是完全基于存储过程的,无论你如何修改数据库结构,只需把代码重新生成一遍就行了。你的任务只是写存储过程,访问DB的C#代码一句也不用你写。所以,我们只要你能写存储过程就OK。等有空把它共享出来。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页