面试题,谁会做?(0分)

  • 主题发起人 主题发起人 ygq
  • 开始时间 开始时间
余六:
我想这个问题应该已经解决了,在RE 3.1中,客户端并不需要一次取得
所有记录,而只是获取需要显示的数据,所以打开一个分类时取得的数据
只有十几条。
我用Interbase试过,打开任何一个分类的速度都小于1秒,SQL Server也
类似。
SQL数据库的好处在于,只会取需要的数据,而不是一次提取所有的数据,
所以如果用access数据库,怎么也需要30秒以上的初始时间。
如果是web方式的话,就更加简单,因为web每次只需要显示固定数目的
记录(比如20条),那么服务器传过来的数据就绝不会超过20。
 
各位不要在数据接受、传输方式上打主意,关键的瓶颈在
1)数据表庞大,sql执行慢;
2)返回数据量大,网络拥挤;
3)客户端临时占用内存很大。
解决办法1:
1)在服务器上做一组存储过程,用全局游标获取记录,然后反馈到客户端;
2)启动微软的那个数据事务服务器来减轻第一个问题;
3)采用存储过程加全局游标也抛弃了客户/服务器这个概念。
解决办法二:
全靠微软的数据事务服务了,执行以下语句:
declare cnt integer;
select top cnt * from table;
set cnt=cnt+10;
这是一个窍门,利用一下微软的事务特点,只能用在mssql上,也可以高效的实现要求,
唯一的代价是服务器大内存。
 
各位,不好意思,我只不过想挣点小钱花花,因为我很难登陆到大富翁上。
解决的方法很简单,只是也花了脑筋和实验时间,利用这个机会,当然想得到收获的机会。

方法如下:
如本来根据要求服务端要取出Select * From Table Where field=1,假如符合条件的共有
四十万条,即使客户端分段下载,服务端也需全部打开记录,当然慢得够呛。
那么,我们合不减轻服务端负担,在服务端也分段下载。
在SQL Server中,用Select Top 30 * From Table where filed=1 and iID>n order by iID,
第一次,客户端送给服务端的参数n为0,既得到全部的符合条件的头30条记录。当客户端
下拉滚动条到最后一条记录时,表示需求下面的记录,于是用另一个ClientDataSet2去找
数据,此时用的语句为:Select Top 30 * From where field=1 and iID> lastiID order by iID,
其中LastiID为ClientDataSet1中的最后一条记录,然后用AppandData加到ClientDataSet1中。
这样,客户端是浏览多少就向服务端要求多少,而服务端则也是客户端要求什么就只收索相
应30条,两边负担都不大。而且,据我实验,Sql Server 执行 Select Top 30 * From Table
的速度还是比较快的,基本感觉不出来。
其他数据库同样可以用同样的方法。

to ALL:
若你们觉得这个方法对你们还算有用或能有所启发的话,就看着给些辛苦分让我花花。开出送分
来标题来,我一定接着。:》

to 左轻侯:
你可以考虑看这种方法能不能改进你的离线浏览器的速度,免得我自己动手了。




 
--同意guqs;
--需要一张临时表存放全局变量LastID;需要假定某个排序的字段存在,如LastID

Create procedure sptest
AS
Declare @LastId int
Select @LastID=LastID From tblLast
Select top 10 @LastID=uid From tblTarget Where Age>30 and id>@LastID Order by id
Update tblLast Set LastID=@LastID
Select top 10 uid From tblTarget Where Age>30 and id>@LastID Order by id


 
guqs的方法大家看值多少,我出好了
 
做了个控件,应该可以实现这个功能。
 
不知数据库是什么数据库,如果是MySQL问题就好办了,用guqs的办法,实现起来要快得多,
因为专门有现成的语句,别的数据库就只有完全采取guqs的办法,用存储过程,搞定。
 
guqs:
你的方法早就在RE 3.1中实现了,我已经在上面说过,RE 3.1自己实现了缓存功能,
客户端并不需要一次取得所有记录,而只是获取需要显示的数据,所以打开一个分类
时第一次取得的数据只有十几条。LastID不需要临时表来储存,在程序中设一个全局
变量就是了,可以看看RE 3.1的源码。
至于select top X的语法,我觉得没有什么必要。以我的理解,SQL数据库与文件型
数据库最大的差别之一就在于,SQL数据库并不是一次性打开所有的数据,而是只查
询和发送客户端确实需要的数据。据我在Interbase中试验,即使是select * from
letters,也在1秒之内执行完毕,当用户向后滚动时,数据库才会继续查询并且将后
面的数据发送过来。我认为select top X只是语法上比较方便,在性能上并没什么
提高,除非客户端一次性Fetchall。
 
to leepin:
LastID并不需要临时表存,也不需要全局变量存。只需要在ClientDataSet需要继续取数据
时,把ClientDataSet的最后一条记录去处,作为服务端Query向下继续查找的条件即可。

to 左轻侯
你可以试一下,在SQL Server2000的查询分析器中,用Select * From Letters,若Letters
有40万条记录,查找时间为48秒;若加上Top 30,只找前三十条,查找时间为瞬间,显示时间
为00:00:00,天壤之别。
若不加top 30,当符合查找条件的记录非常多,如查找所有已答问题,若记录为40万条,Query
将找到所有记录,速度非常慢,而限定条数后,Query就很快了。


 
to 左轻侯:
"你的方法早就在RE 3.1中实现了"
我刚才简略看了一下,你的RE3.1似乎并没有实现与我类似的方法。
比如你的查某一分类,用的SQL语句为:
"select id,subject,userfrom,points,datetime,replytimes,status from letters where parent = 0
and RoomID=XX order by order by DateTime DESC"
并没有限定其他条件,假如这一分类中有上十万条记录呢,你若用Query岂不要全取出来?

但你用的是原生ADO,好象原生ADO有自动分页,也许本身可以分段取数据吧?(没仔细研究过)。

但余六所说:“几十万条数据在本地处理的速度不堪忍受,我把数据导入了小服务器里速度立刻提高,
但第一次下载也要1分钟”又是怎么回事呢?
 
To:guqs
你的方法思路不错,呵呵,我开200分给你
http://www.delphibbs.com/delphibbs/dispq.asp?lid=549467
我开始用左轻候的浏览器,Access数据库,在98下打开就死机,在WIN2K下用时3分
打开目录数下的条目,再点开下面每个帖子都需要用时2分左右。
后来把数据导到一个COMPAQ(pIII 500,256M内存)小服务器的MS SQL 7上,打开目录
树要1分多,但是浏览下面帖子就只要1~2秒。
再导入HP服务器上(4*PIII 800,1G内存),浏览如飞。
 
多谢余六如此慷慨。

余六的实际使用看来证明了原来原生ADO并不能自动分段取数据,即使分页,也要先一次性
取出来。也说明了左兄的RE3.1还可以在速度上优化一下。
 
好内容啊!!!
PS:如果不继续讨论应该考虑存档了:)
 
guqs,:你的想法好象有点象李维的想法嘛
 

Similar threads

S
回复
0
查看
859
SUNSTONE的Delphi笔记
S
S
回复
0
查看
784
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部