能否用Delphi写大型的WebApp(WINCGI/IISCGI/SOAP),非高手莫进 ? (yysun老师在哪?)(0分)

  • 主题发起人 主题发起人 Rocklee
  • 开始时间 开始时间
学习中,好久没有看到这样深入的讨论了。
 
我也来说两句,我以为的瓶颈是数据库设计得太单纯了。
如果数据库做小的应用,记录在10万以内,那怎么做都不太有问题,因为很烂的一句sql都
能很快的运行。可是,到了数据量到一定程度以后,结果就完全不同了,任何有一个查询
都会很耗时间,时间耗在哪里呢?一般,sql server的cache已经把索引弄进内存了,所以
不在索引上,应该在输入输出上,一个大表,既便是仅仅把主键提出来也非常大,够耗上
点时间的,更何况还有应用程序要用这些数据的时候中间传递过程。而象大富翁一样,翻
有页有各种可能性,特别是有的时候是全文检索查询!那更是没法优化,真正是一个瓶颈。
那真的没有办法吗?绝对不可能。回到我前面说的一句话,数据库设计得太单纯了,几
乎仅仅是存放数据和提取数据,数据量大后,那当然慢了。如果把数据库本身设计就当成
一个应用,一个考虑效率的应用,那情况就完全不同了。
就本人经验粗的有以下几点。
1)在数据库设计之初就要考虑到架构问题。比如webApp当然是更象好一个无状态应用,
而c/s则有要快也许需要利用rds等技术。
2)很多查询是多余的,可以作为更新,增加,删除的一个触发事件后应用写到辅助的表
或者字段中。比如大富翁现在的每人回帖数,就是一个不必要的查询。原因很简单,写
虽然多花了时间,但读却大大快了,而对数据库主要还是读。
3)sql语句的性能优化,有很多人并不很熟悉存储过程,比较数据库设计应该是专门的
而起写存储过程一般都不兼容,移植性能很差。但是很多人写的sql语句确实很没有效率,
稍微改一下,就可以成倍的提高速度。我可以给一个统一的准则,就是尽量利用索引,
如果有相同效果的语句尽量使用I/O消耗小的,尽量在提取数据的时候使用更多,更细致
的判断和过滤,能少提数据就少提。
4)有些特殊的用法,但也是很常用到的用法,比如翻页,确实是一个更复杂的应用。而
不应该是一个简单的查询了。如果给你的是一个数据结构的问题,要你从某个排序中提出
某条记录之后的n条记录也许你会做的很好,同样是数据库怎么就不行了呢?更何况数据库
引擎把hash,B树可都是做好的呀。而且关于查询还有一个查询持久性的问题,很多查询
需要不需要反复查,再次查呢?肯定不需要,比如今天这个帖子里含有“问题”这个词,
难道明天就没有了吗?不会,所以完全可以把他记下来,下回查的时候忽略它,只要查
新的记录就可以了。
5)不要迷信很多关于性能的神话,比如存储过程,query因为是编译过的会快些,这些
性能的提示非常有限。性能的问题还是取决于架构、数据流量、算法!
 
简直是太棒了,真希望这种深入的讨论能多一些,这样大家提高得有多快啊! 收藏
 
yysun老师谈得非常深入,我只是发表一下我的几点体会:
1)就midas系统或者大型WebApp而言,系统的性能很大程度上取决于数据库的应用设计,当然,
我赞成尽量减少客户应用端的数据流量(均衡响应速度),所以说楼主开始说的要查询出10000条
记录一次性传送到客户端,我同意yysun老师的观点,实属错误的设计(不排斥特殊情况)。不过,
就数据库服务器本身的查询的效率而言,适当的用索引和正确的建立索引也是有很大的关系的,
yysun老师上面的存储过程就很能说明问题。
2)就楼主所说建立大型webapp而言,我个人提倡用jsp/servlet+bean(可能我的观点不够正确),
我想大家对于它与asp,cgi,isapi的优缺点已经有所了解,就我个人认为它的编译型和在虚拟机上运行的跨
平台性已经有足够的说服力,而且java语言也是一门优秀易懂的语言,至于没有ide纯属自己不会
搭建而已,网上有很多这方面的资料。
 
请教楼上各人兄
在delphi6+upd2后有个问题
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在服务器端,建立了一个WebService,并且加入了一个DataModule(定义名称为:DataAccessMod)。在DataAccessMod中加入了ADOConnection,ADOQuery和DataSetProvider。运行后注册服务,可以用IE正常看到已经注册了IDataAccessMod接口。
然后建立客户端程序:加入SOAPConnection,设置URL指向IDataSrv接口。然后加入ClientDataSet,选择RemoteSrv为SOAPConnection。但是在ProviderName中无法看到服务器端的DataProvider名称。
虽然将接口是从IAppServer改成从IAppServerSOAP可以了。但在客户端clientdateset中看不到任何DataSetProvider了
用起来非常不方便
请教楼上各位人兄,那个知道解决方法
(在delphi7没上述问题,但末注册时显示unregistered。使用中不知功能有没有限制)
另外,请教楼上各位人兄,那个知道服务器分发时要怎样设置?客户端若使用SoapConnection1时URL怎样设置?
一个初哥 Hj-andy@163.com
 
经典收藏。。。
 
哈哈,分页取数据确实是一个问题,我个人认为,
查询时把上次查询的结果集的最后一条纪录的关键字传递过来就可以了,
可能客户端多一点点代码,但整体上速度和方便性都会上去。
多层结构,应该考虑代码复杂度,服务器速度,可移植性等等的要求限制,
把应用逻辑合理的分配,最重要的是要给用户一个稳定、高效的系统。
另外我推荐中间层用Java来写,没必要因为自己是老的Delphi程序员就什么都用
Delphi来写,毕竟每种语言都有它的有点,Java在中间层的地位不是炒作出来的,
但客户端可以用Delphi+Soap来实现,没什么问题,.net本人现在还没怎么用,我们的
用户不敢用IIS,他们不是专业的防黑员,随便到网上找找,都是IIS的漏洞...[:D],
现在应用服务器大多都是WebLogic,WebSphare等,大家应该顺应潮流才对,技术是用来
为客户创造价值的,不是用来赌气争论的.
 
能否用Delphi写大型的WebApp(WINCGI/IISCGI/SOAP),非高手莫进 ? (yysun老师在哪?) ??!!!
靠!不是高手别进来???什么狗屁话!你没有资格在这里法贴!不自量力!狂妄!
 
好,算我自大行了吗?
其实并非有此心,只是不想有人在这贴子上灌水,才这么说。
这里是技术论谈,不是骂战的地方,如果有人想灌水,请到别的地方去。
 
yysun的确是功力深厚的老前辈啊,
 
YYSUN的风范可见一斑。
不过YYSun要常来给我们大家解惑呀。
 
你对操作系统一无所知。你懂得甚少。
 
对,我对操作系统一无所知。
你用Delphi写个Web service然后在win2000下跑
然后多开几个Client(当然要进行一些查询或修改记录之类的操作),
每开一个Client,然后看看你那个web service占用内存变化就知道了。
呵呵,真的好一段时间没空,都跑到java那边开发了。
真不好意思。
 
刚刚做过一个分页的东东,想上大富翁寻找更好的方案,看到这个帖子,我也来说几句。
先补充一个我曾经用过的,刚好类似于USP_SPEED3的方法,称为USP_SPEED4吧。
USP_SPEED4:(PageSize:每页记录数,PageCount:页号)
Select top * from
(Select top PageSize * from
(Select top PageCount *PageSize * from 视图 where 范围条件 oder by 排序条件 升/降) as A
order by 排序条件 降/升) as B
order by 排序条件 升/降
几个方法如果从算法本质的角度看是一致的,首先对满足条件的记录集合排序,确定最大至当前页号的记录,然后取出这一集合的最后一个页的记录,他们的基本模型是一致的,参数是:视图(总范围限定条件),排序条件,排序方向,单页记录数,页号,由于有这个本质,因此不论具体的数据库环境如何,总是可以设计出符合这个模型的通用方法,因此usp_Speed1-4方法都可以通用化。
具体的效率我们来分析一下:
usp_speed1方法走了弯路,将记录取出来之后,再手工为其产生顺序号。数据库内部已经为每条记录产生了内部顺序号,这个方法没有使用到它。而且除了查询操作外还有插入操作,在无谓的记录上浪费了大量时间,这种方法硬盘写操作所占的比率大,耗时就多。而且这样的操作不具备需要缓冲的性质,任何时候执行耗时基本一样。
usp_speed2利用到了记录的内部顺序号,但是它显式的要求数据库返回游标结果集,比起后两种方法,申请了和耗费了更多的资源和时间。
而后两种方法利用的top这一带有顺序计数性质的关键字,排序和取数在数据库内部完成,如同soul讲的‘更何况数据库引擎把hash,B树做的很好了’,它的效率不是你编写的过程可以比较的,更何况它在底层办事,你在它提供的层层接口上办事呢?
一般来思考,usp_speed4又显得更加简单。我第一次看到usp_speed3时想:你的第一个子查询已经把取了一把记录了,又not in一次在整个视图范围里面把这些记录剔掉,不如usp_Speed4取一次记录,然后通过排序就可以取到这把记录的顶部你要的那页记录了。而且方法3依赖与一个rowID字段,这个方法不需要rowID字段,适用范围最为广泛!
于是做了个测试,我的电脑配置不高,c1G,7200 40G硬盘,384内存,91万条记录,盗版Sqlserver Enterprise2000,打开了执行计划窗口,同时还运行了word等程序,结果发现在页号不大的情况下,方法4比方法3快50%到20%,但是,让我惊奇的是随着页号的增大,也就是是随着子查询返回的记录越多,方法3的速度反而快过方法4,而且其速度加快了。在pageCount*pageSize=3000的时候,方法3耗时58s左右,在pageCount*pageSize=800000的时候,居然只要30s!而方法4却要2分多种,而且其执行计划完全不同于3000数量级的执行计划,但方法4的执行计划始终没有变化过。我猜测是Sqlserver自动判断了查询的规模和现场,采用了相应的最优的执行计划(这些有趣的现象,希望可以为帮助大家推测Sqlserver的工作机制提供‘料’)。单从查询结构上来讲,方法3的语句结构在Sqlserver的角度上讲更好,因为Sqlserver可以对其产生不同的执行计划,以获得最佳效率,而方法4的语句结构Sqlserver就只能死用一种执行计划了。
这些从某个方面告诉我们,为什么我们需要受到专门培训的经过专门认证的专门数据库的专门数据库设计和管理员了!^_^
但是,最后我没有采用任何上面一种方法来实现我得分页功能!尽管我曾经采用过方法4这一简单偷懒的方法,但最后迫于用户的压力,放弃了。顺便说一下,我们的系统是cs结构,用户要求滚动数据时完全没有可以感觉到的停顿(半秒也不行,但是….0.2秒说不定可以不被感觉到^_^),而打开这个数据浏览窗口时必须刷的打开。这个操作有40个并发的可能,有15个用户如果业务繁忙的时候每天执行这个操作最多可达到上千次(具体数字我也不知道,但是有这么个统计,在业务最繁忙的时候,原来(Dos系统,类似操作无停顿)他们要加班到9点钟,现在要通宵加班,不停的开单,经过改进后,只要加班到12点钟了~~~~~(还有其他效率瓶颈,受系统平台限制没法解决))
我最后的解决方案如下模式:
select * from
(select top n from table whre FieldA>Value order by FieldA
union
select top n from table where FieldA<=Value order by FieldA desc) as A
order by A.FieldA,之所以取某个点前后记录是因为用户不要分页方式浏览,要滚动数据浏览。
Yunye也提到过,把上一次查询最后的关键值传过来,作为下一次查询的基点参数。不过我还想说详细一点:
1. 这个不会随着页码的增加而时间增加,他的时间复杂度最优,只与单页记录数相关,与页码规模无关。设置了索引后,甚至与表的规模无关,真正做到了‘无停顿’,即使在100万条记录的时候。而且,它充分利用了缓存!(第一次执行需要1秒钟,第二次执行可就‘刷’的出来了)
2. 这种方法的模型基于哈希索引模型,我认为这种模型好于顺序索引模型。形象的说:这种方法就好像给了地址直接就定位到了目标页处,而前面四种方法不论是利用内部的还是外部赋予的顺序号,实际上都需要显式或隐式的‘遍历’至少所有页码。实际上,数据库系统就是利用哈希表或B树来完成这种查询的。
3. 绝大多数情况都可以使用该方法,虽然它依赖具体某个或多个字段进行值判断。但是,无法依据字段值实行排序逻辑的用户需求可以说是不存在的,否则就是你的系统设计存在问题,或者是数据库设计有问题,应当检讨设计,而不是检讨这个方法。如果出现个别想象不到的极端情况,再寻找个别特殊的解决方法。
好了,我说的差不多了,补充几点:
1. 通用性没有好与坏之分,只有适用目标范围大小之分,这个是受其通用模型决定的。不同环境可能实现代码不同。
2. 个人性质的观点:我不同意从代码形式的角度评价某个方案,应当从其功能和适用性去评价,和他的逻辑。有的方案可能表面上曲折复杂,但是其实施概念和逻辑却清晰,易于表述,就是好方案,更甚至,一个方案可能不是最好的方案,但是能被整个项目组统一理解,那就是可行的方案。
3. 总之,用户需求第一,系统性能与系统的工程结构其次,最后才是程序员的工作量。
在保证系统对用户产生的实际价值的前提下,才考虑需求设计与变更,在有了确定的需求后,才考虑系统设计,系统设计首先考虑功能和性能水准, 然后确定方案,最后实施-编码,
至于程序员反映限制了创造性或者感觉上头的方案太烂的话,就找一个天才一点的做头子,搜集问题,带领他们解决编码阶段的问题,不然就让他们郁闷去吧,只要整个系统按照计划和步骤受控,客户不嚷嚷就行了,^_^…………程序员的无奈……….但也许是软件工程业的欣喜……如果有一天程序员能达到像在流水线上的机器一样的水平……..老板就开心了…….也许老板需要发现和培养几个程序或软件天才………但决不需要个个都以为自己是天才…….也许老板需要鼓励个性发展…….但决不需要每个程序员在软件过程中表现个性。唉,越说越远,恕我多言。另外,此文编辑时,光标回退最多不超过10个字符(言下之意,就是决无删节,一气呵成,自我陶醉中……扔西红柿吧)
 
谢谢 djflying ! 您补充的内容:使用 union 来支持滚动,又使我们大开眼界。
目前,大富翁论坛正使用类似 usp_speed4 的算法,并配合适当的复合索引。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1438997
> 如果有一天程序员能达到像在流水线上的机器一样的水平
这个就是软件开发成为产业的基本条件。
 
对楼楼上的发言,做了测试.如下
环境:SQL 2000.数据库为系统自带的NorthWind库.
select * from
(select top 10 * from orders where orderid>10248 order by orderid
union
select top 10 * from orders where orderid<=10248 order by orderid desc) as A
order by A.orderid
大家知道.Union无法用Order by 不知道楼楼上如何在具体项目中用这条语句来取数据的
很是不解,盼解惑........
 
后退
顶部