关于ClientDataSet的递增式数据获取,请大家发表自己的见解。 ( 积分: 200 )

  • 主题发起人 主题发起人 kkkchenA
  • 开始时间 开始时间
K

kkkchenA

Unregistered / Unconfirmed
GUEST, unregistred user!
利用ClientDataSet的递增式获取数据是不错的选择,可以大大缓解网络传输的压力。
为了更加有效率,服务器要池化,所以服务器端的DataSet用完就关掉了,把它当前的状态通过OwnerData送回到ClientDataSet让它自己保存状态(就是记着最后的那条数据)。
ClientDataSet要获取下一个数据包的时候通过OwnerData把自己的状态传送过去,让DataSet打开以后定位到相应的记录上,这样DataSetProvider就可以把第二个包打包返回了。
但是,每次的数据定位太浪费时间了,特别是一些有大量数据的表。昨天看了一个存储过程,它用Top关键字来实现数据分页提取,我觉得我也可以用Top关键字,加上主键来定位数据,让DataSet只取回PackSize条的数据。我在DataSetProvider端,根据ClientDataSet保存的状态值,来对CommandText进行修改,把它改成这样的形式:
Select Top PackSize From TableName Where KeyField>KeyValue Order by KeyField
PackSize:包大小
KeyFiled:是主键
KeyValue:上一个包最后一条数据的主键值
这个语句实现了让DataSet只拿回一个包大小的数据,打开速度大大提高。在一个有1000万条数据的表中测试,浏览数据时,基本上感觉不到停顿。
我想知道的是,这样的处理会不会带来什么后遗症?
请大家发表一下自己的见解,如果有更加好的提高效率的方法也请发表一下。
另外我还想知道DataSetProvider是怎么通过DataSet获取从表的数据的,他是怎么知道存在从表的呢?看了一下DataSetProvider的代码,没找到从表的表结构获取部分的代码,估计应该是在DataSet里面自己完成了。
 
利用ClientDataSet的递增式获取数据是不错的选择,可以大大缓解网络传输的压力。
为了更加有效率,服务器要池化,所以服务器端的DataSet用完就关掉了,把它当前的状态通过OwnerData送回到ClientDataSet让它自己保存状态(就是记着最后的那条数据)。
ClientDataSet要获取下一个数据包的时候通过OwnerData把自己的状态传送过去,让DataSet打开以后定位到相应的记录上,这样DataSetProvider就可以把第二个包打包返回了。
但是,每次的数据定位太浪费时间了,特别是一些有大量数据的表。昨天看了一个存储过程,它用Top关键字来实现数据分页提取,我觉得我也可以用Top关键字,加上主键来定位数据,让DataSet只取回PackSize条的数据。我在DataSetProvider端,根据ClientDataSet保存的状态值,来对CommandText进行修改,把它改成这样的形式:
Select Top PackSize From TableName Where KeyField>KeyValue Order by KeyField
PackSize:包大小
KeyFiled:是主键
KeyValue:上一个包最后一条数据的主键值
这个语句实现了让DataSet只拿回一个包大小的数据,打开速度大大提高。在一个有1000万条数据的表中测试,浏览数据时,基本上感觉不到停顿。
我想知道的是,这样的处理会不会带来什么后遗症?
请大家发表一下自己的见解,如果有更加好的提高效率的方法也请发表一下。
另外我还想知道DataSetProvider是怎么通过DataSet获取从表的数据的,他是怎么知道存在从表的呢?看了一下DataSetProvider的代码,没找到从表的表结构获取部分的代码,估计应该是在DataSet里面自己完成了。
 
并不是所有的数据库都支持Top关键字
 
该方法(取top packsize)大大缓解了网络压力,我也是这样来获取大批量数据的,基本还没发现什么问题.我发现把每批的数据量设为900效时比较好.
 
TO 放飞
嗯,如果是不同的数据库的话,应该需要不同的改造方法。
 
我觉得,尽量不要让用户(或者说是客户端)有打开某个表的所有记录的机会。
好像在哪本书上讲的,当返回的数据集占总数据的30%(大概是30%)以上,那么数据库的索引基本上就不会提高检索的速度了。
因此,尽量让用户去精确检索数据。让一次业务上的检索返回尽量准确的数据集,才是减少网络上数据流量的根本,这样也能更节省用户的眼球[:D]
 
TO 放飞
您说的对,但是对于存在1000万数据的表,就算让用户自己来定义数据的范围,可能每次服务器要返回的数据都是很大的,我上面的修改是限定它每次获得的数据的量,也许一次只返回它能在Grid上看到的那么几条数据,那么他看到最后一行时,ClientDataSet会自己去获取下一个包的数据。只是做这样的一个修改而已,这样做保证了每次都只获取少数的数据,呵呵,这个是PackSize的好处。
 
1千万确实有点太多了,检索个 姓名="XXX"恐怕都会出来个百八十条的,
不过,要是再加上 性别="X"
and 身份证号="XXX",估计就没几个了。
在前台给用户看的数据,应该都是用户关心的数据,我想除了开发人员,很少有人喜欢把所有的数据都整出来看一看。
当然,我说的也只是片面的。CDS提供的这个PackSize还是不错的。但是,这个属性尽量少用,因为这个属性会让服务端为你保留状态信息。应该说,PackSize这种思想是好的。但是最好还是自己去实现这种思想。
在大批量数据的传输上,采用分包传输的方式,在设计上应该是必须的。
但是在客户端,要尽量减少有大批量数据检索这样的请求。
好好划分其业务逻辑,应该可以让这种存取大批量数据的机会减少很多的。
另外,如果从服务端获取了太多的数据,那么数据的一致性的维护也很不容易。
 
呵呵,其实我的服务器端的DataSet是每次数据打包返回以后都Close的,Cds获取下一个包的状态信息通过OwnerData返回客户端让它自己保存状态,每次获取数据的时候通过OwnerData传递到服务器端,服务器端的DSP根据传过来的状态修改CommandText重新赋值DataSet的CommandText属性来获得新数据。
服务器端并没有保存状态的必要。
现在还有个想法就是在CDS上定义表,表关系,获取数据的时候翻译成SQL送到DSP来执行返回数据,我现在对DSP获取从表数据部分还不是很了解,所以还没有动手,相信完成以后,服务器端就没有DataSet存在了。弄一堆DataSet在服务器端的RDM上确实很烦。
 
结贴了,好像没多少人喜欢这个题目。
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
730
SUNSTONE的Delphi笔记
S
后退
顶部