bde的query第一次更新sqlserver怎么会这么慢???急!!!(200分)

  • 主题发起人 主题发起人 liangliang
  • 开始时间 开始时间
to huawdg:
另外,我突然想起来了,query是不能用refresh,你是怎么刷新的?
 
query1.open时,FETCH
query2.EXESQL,没有FETCH
刷新:
QUERY1.close;
query1.open;
 
to huawdg:
请问你的表有多大,如果表很小的话,bde会在你开query1的时候会先把所有的数据都拖回来。
这样,更新时他是不会先fetch的,如果很大的话,向我的表(20000左右),它在open时只先fetch了前200笔,
而在第一次更新时先把剩余的18000笔fetch回来,在更新的。
我的意思是你看看他第一次open时候是不是把所有的数据都fetch 回来了?如果是更新时自然不会fetch,
如果是这样的话,你能不能帮我实一个大一点的表,谢谢了。
另外,你select 的表,和update的表是不是同一个表啊?
为什么我的就是会返回阿, 你有没有设么特别的设置阿。我用的全部是默认设置,就是控件拖下来的设置。
 
我觉得应该是这样的啊
其实当你的query1打开时,就应当全部fetch回来的,(SELECT * FROM ATABLE)
只不过delphi帮你缓冲了一下
我不知道 ORACLE,在QUERY1打开时,是不是全部FETCH回来了。
 
to huawdg:
应该是这样的?
为什么?我只是要更新一笔数据而已啊,没必要全部拉会本地啊,他完全可以继续缓冲啊?
我用sqlmonitor分析过bde连oracle的做法,它只拉回,需要更新的那一笔,那么同是bde威慑么所用的策略相差这么多呢?
那如果是这样的话,是不是可以得出这样的结论:
只要bde有连着那张表,或者用requestlive=true的时候,更新那张表的任何字段,都会先把那张表的所有数据线拉回本地。
那这样的效率也太低了吧,这样话,bde第一次更新sqlserver的效率是很低的咯?
 
不是!
从愿望出发,既然能缓冲,那继续缓冲多好!
从道理出发,是你 SELECT 了全部记录,当然将全部记录返回给你
从合理方面讲,如果你 SELECT 了全部记录,没有当时全部返回给你;
然后你 UPDATE;然后你想看看先前SELECT的记录,你希望看到UPDATE之前的记录呢,
还是UPDATE之后的记录呢?当然应当是UPDATE之前的记录,因为你是在UPDATE之前SELECT的!
UPDATE之后的记录应当刷新后才能看到。因此在UPDATE时,将未完成的FETCH完成是合理的。
(你试试ORACLE这种情况时会看到什么记录?)

你再试试,query1.SQL :SELECT TOP 50 * FORM ATABLE,打开它
然后,QUERY2 进行UPDATE,你看是不是会FETCH
事实上,UPDATE是不会FETCH任何记录的。

建议,既然你的QUERY2 UPDATE之后,QUERY1要重新刷新,你可以先以CLOSE QUERY1,
再QUERY2 UPDATE,再OPEN QUERY1。
我始终认为这是程序设计问题,而不是系统问题
 
to huawdg:
->从合理方面讲,如果你 SELECT 了全部记录,没有当时全部返回给你;
->然后你 UPDATE;然后你想看看先前SELECT的记录,你希望看到UPDATE之前的记录呢,
->还是UPDATE之后的记录呢?当然应当是UPDATE之前的记录
首先,即便我需要要看update之前的纪录,那在query1.open的时候已经拉回来了,威慑么还要在拉一次呢,
如果说open的时候用了缓冲没有全部拉回本地,更新的时候需要先全拉来回来,这就有些奇怪了。
1。威慑么需要拉回来,我看不出更新操作必须要先拉回所有数据有什么必然联系(事实上,oracle也会拉回来,但是只拉回更新的哪一笔,
这还想得通,因为可能,在修改这笔数据前,可能已经有别人也修改过了这笔数据。)
2。就算说是因为query1连着,需要来拉回来,威慑么需要全部拉回来,我是说既然第一次open使用了缓冲,那么现在为什么就不用缓冲了呢?
3。如果说是因为open 和 update 之间可能有别的用户更新过该表,需要在更新
前在拉一次回来,那么威慑么,第2次更新就不用全部拉回来了呢?

-〉(你试试ORACLE这种情况时会看到什么记录?)
之前我说过:‘我用sqlmonitor分析过bde连oracle的做法,它只拉回,需要更新的那一笔‘,不会全部来回来,
我觉得这样的策略是对的。

-〉建议,既然你的QUERY2 UPDATE之后,QUERY1要重新刷新,你可以先以CLOSE QUERY1,
再QUERY2 UPDATE,再OPEN QUERY1。
这个方法我知道可行,但是如果我非要有一个query连着呢,实际操作中我不可能每次修改一笔数据都
先q1.close->q2.update,->q1.open 啊,我要把那表显示在一个dbgrid中的,同时用户要修改莫笔记,
这样做,grid岂不是,一闪一闪的。而且效率也不会高吧。
再如我以前说的第一个例子
如果,我要在grid中修改用query返回的数据,是不是铁定要先把所有数据都来回本地啊?
 
-〉(你试试ORACLE这种情况时会看到什么记录?)
之前我说过:‘我用sqlmonitor分析过bde连oracle的做法,它只拉回,需要更新的那一笔‘,不会全部来回来,

我是说,UPDATE后,QUERY1不刷新,这时你在DBGRID中看到的是UPDATE之前的记录,还是UPDATE之后的记录?
如果是UPDATE之前的记录,说明即使ORACLE,也是全部FETCH回来的(前提:QUERY1: SELECT * FROM ATABLE)
如果是UPDATE之后的记录,那说明ORACLE有问题了! 既然在UPDATE之前就SELECT了,
并且 UPDATE 后QUERY1没有刷新,怎么看到UPDATE之后的记录呢?(前提:QUERY1: SELECT * FROM ATABLE)
 
to huawdg:
-〉如果是UPDATE之前的记录,说明即使ORACLE,[red]也是全部FETCH回来的[/red]:
没有,我说了,他只先拉回那笔需要更新的数据,你可以自己用monitor 看看。

至于威慑么你能看见update前的数据那是因为在update前,query1.open 了,他当然返回了,
你看到的已经返回的数据啊(是在open之后,update之前的本来已经返回的数据),
另外,如果open的时候,量很大的话,他也会缓冲(不过是在open的时候,不是update),
这时,你可以试者,拉动dbgrid的右边的那个下拉条到底,你再看sqlmonitor,发现此时他才开始fetch
所有的数据到本地(所以是在,你请求需要返回所有数据的时候,他才这样做,一般都是缓冲的)

 
我理解你的意思了。
是不是这样的:
ORCALE 可以把符合 SELECT 条件的,尚未 FETCH 回来的,即将被 UPDATE 的记录,首先 FETCH 过来,
而不是把余下的记录全部 FETCH
这个技术确实不错!
SQL SERVER 为什么不行,兄弟我才疏学浅,帮不上忙

请高手指教,也让我学几招!
 
我觉得应该是只需返回需要更新的数据就可以了,至少我看不出必须全部返回的必然理由。
同样的,用ado的就不会这样,他也只返回需要更新的数据。
如果说bde就是用的这样的策略,那我也就死心了,可偏偏用bde连oracle就不会这样。
连sqlserver就是会这样,真是想不通,同一家的东西啊,难道sqlserver有什么特别的吗?

会不会还有什么地方可以设置设置的,还有那位高手指点指点阿???
 
*sigh*
为什么这么多人都不用最正统的缓存提交方法呢
TQUERY (cacheupdates=true,requestlive=false,updateobject=XXXXXXX)+Tupdatesql
绝对不会有你不想要的数据来回的.
 
to 李大嘴:
Query1.CacheUpdates:=True;
Query1.RequestLive:=False;
Query1.UpdateObject:=UpdateSQL1;
Query1.SQL:='SELECT * FROM ATable';
UpdateSQL.ModifySQL:='UPDATE ATable Set AField=:AField Where ACondition';
DataSource1.DataSet:=Query1;
DBGrid1.DataSource:=DataSource1;

Query1.Open; //FETCH 若干行
Query1.Edit;
.....
Query1.ApplyUpdates; //FETCH 剩余行,再更新数据库

老样子啊! 是不是我的方法有问题?

 
to 李大嘴:
->为什么这么多人都不用最正统的缓存提交方法呢
->TQUERY (cacheupdates=true,requestlive=false,updateobject=XXXXXXX)+Tupdatesql
->绝对不会有你不想要的数据来回的.
你真的是试过了吗?
我的测试结果,当post时他确实是什么都没干,可是在applyupdate, commit后,你再看看
sqlmonitor, 他先在做什么?fetch,fetch............,还是在返回所有数据阿
 
看来这是BDE缓冲处理机制的问题,
先想个法子规避吧,
以你的第二个例子为例,再建一个TDATABASE,连接同一个数据库当然,DATABASENAME要不同
你的执行UPDATE语句的QUERY的DATABASENAME设为该值,
应该可以达到目的了,
这回我是试过了 :)
当然,只到这一步还不够,因为你的第一个Query还没有更新, 老是close open也不是个办法
我是这样想的,希望对你有用
因为要改很大的表,一般此时为了性能考虑只宜一个事务改一条记录,
首先 query+updatesql标准组合是一个可更新的数据集,用于查询,修改,显示,记住不要做
applyupdates!!!!
再建一个TDATABASE,假设为DATABASENAME为'REALMODIFY'
然后在一个合适的时候,你可能修改了一条记录确认要写回数据库,比如是在afterpost事件中
tquery 有一个属性UpdateStatus,指明当前记录状态,是未改还是已修改或新增什么的
假设为usUnmodified,那么,
updatesql1.Query[ukModify].DatabaseName:='REALMODIFY';
UpdateSQL1.Apply(ukModify);

应该可以了,其它一些事务控制异常控制的细节你就自己想吧,
如果希望QUERY中的记录标志回复为'未修改',只调用commitupdates
(不过好象老是执行两次不知道为什么但至少快几个数量级了,呵呵)
打这多么字真累,有什么新的发现告诉大伙啊
 
不好意思,好久没上来了,现在上来给分。
但是这个问题我始终找不到解决的方法,我已经放弃用bde连sqlserver了,现在项目已经开发完成
改用ado连sqlserver.原因是除了我提的这个问题外,后来我发现bde连sqlserver还有其他问题,
不做过不知道啊,原来用bde连pardox好好的,换乘sqlserver就有一堆你想都想不到的问题。实在
实在没有时间号在这些问题上了。一恒心,做了一段批量转换程序,把原来的bde空间全部转成了ado
空间。总算解决了问题。
奉劝大家,除非以前用bde连sqlserver做过项目,否则连sqlserver还是用ado吧,到底不是一家的东西阿。
 
后退
顶部