服务器端游标与客户端游标!进来看看吧。 (300分)

D

doxpix

Unregistered / Unconfirmed
GUEST, unregistred user!
发现论坛上很多FW不推荐使用服务器端游标,大概是出于效率考虑。使用服务器游标的确会
加重服务器的负载,而且服务器/客户端的网络交互请求会大大增加。但是——服务器端游标
的存在也是有理由的。比方对于超过10万条记录的数据库,如果使用客户端游标而又想访问
全部记录的话,除非分批Select数据,否则10条记录必须全部下载到本机的高速缓存中才行
,这时候对内存占有量/速度来说都是一个严峻的考虑。这时候服务器游标就有了用武之
地,设定服务器游标后只需再设置CacheSize就万事大吉了。
李维在他的ADO高级编程里是不推荐服务器端游标的,但是却一再地强调设置CacheSize=1000
能得到最好的效率。可是CacheSize在客户端游标时是根本没有用处的。Why???

另外在使用服务器端游标时,如果出现“OLE DB多步错误”,则需要安装MDAC2.6以上的版本。
而且当游标位置为服务器端游标,而CursorType=ctKeySet时必须保证每一个数据集里有
一个主键字段。

我在使用服务器端游标时,提交一个事务后,常常会出现"ITransaction commit or abort
was called.The DataSet is in zombie state".请问这是什么意思?
 
李维的书不可全信到是真的,他更多的是靠经验,而不是理论.
有好多 Ole DB Provider 现在就不支持服务器游标,或支持得不好.
 
存在的就是合理的->存在的就是有用的!
虽不全对但也不错![:)]
 
SQL SERVER2000的联机帮助比较倾向于使用服务器端游标.
 
视具体情况而定,还有个人的使用经验及熟练成度
 
这个问题,MSDN如是说(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adosql/adoprg04_20hl.asp):
----------------------------------------------------------------------------------------
ADO and SQL Server




Preserve on Commit Property
The Preserve on Commit property specifies whether a recordset remains active after a transaction is committed.

Applies ToCommand Object Recordset Object


Syntax
object.Properties("Preserve on Commit") [= value]

Parts
object

Expression that evaluates to an object in the Applies To list.

value

Boolean that specifies whether a recordset remains active, as specified in Settings.

Settings
Value Description
True After committing a transaction, the recordset remains active. Therefore, it is possible to fetch new rows; update, delete, and insert rows; and so on.
False After committing a transaction, the only operations allowed on a recordset are to release rows and the recordset.


Data Type
adBoolean

Modifiable
Read/write

OLE DB Property
DBPROP_COMMITPRESERVE

Remarks
Preserve on Commit applies only to local transactions.

----------------------------------------------------------------------------------------

可是当使用服务器端游标时,修改ADODataSet的动态属性(如下)
Recordset.Properties.Get_Item('Preserve on Commit').value:= True
会报错--'当对象打开时不允许该操作',实际上在使用客户端游标用上面这一句
来修改动态属性是不会报错的.

看来SQL SERVER在使用服务器端游标时,事务提交/或者回滚后是不会替客户端保存
事务开始之前的数据集的(因为数据缓存在服务器上),需要客户端主动去刷新.

解决办法就是ADODataSet.Requery就OK,但这样实在不是太爽的解决方案:-(
 
都有两面性的
 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbitransaction__commit.asp
 
刚好这两天我花时间再把李维ADO那本看了一遍(已经看好几遍了,每次都有收获)。
你提这个问题,说明你没把李维的书看明白,特别是第四章“深入了解ADO”。
并非SERVER-SIDE CURSOR不好,而且用在什么场合,如果你是在局域网中使用它,那么
因为网速的原因,受ROUNDTRIP的影响相对不会很大。但如果是在Internet环境,Server-Side
Cursor是不可取的。
“当CacheSide逐渐增加之后,Client-Side Cursor在启动数据源联机的时间却和Server-Side
Cursor呈现相反的情形。Client-Side Cursor的表现似乎随着CacheSize的增加反而变得愈
来愈好。我想这是因为要传递到客户端的信息更能够充分地利用TDS Packet Size的原因”
-P241
“在Client-Side Cursor中,如果CacheSize设定为1,那么由于数据源只传递一笔数据到
客户端,因此不但没有充分利用TDS Packet Size,而且当客户端应用程序浏览数据时,
ADO引擎又需要再次向数据源要求取得下一笔数据,因此非常没有效率。当我们稍为增加
CacheSize之后,这个情形可以很快获得改善。”-P242
由此,怎么能说
>>可是CacheSize在客户端游标时是根本没有用处的
呢?
并且,“10条记录必须全部下载到本机的高速缓存中”,就是一个对Client-Side Cursor
和CacheSize不理解的表现。李维在书中提及“少量多次”的原则,就是说利用适当的CacheSize
(100)用Client-Side Cursor在客户端中本地高速缓存的优势,达到最佳的效能。
李维的观点不能说是绝对正确,但他自己也说到要根据不同的环境灵活运用这些Cursor,
他更多用数据,用符合逻辑的原理性客观阐述来说明问题。
我也还有很多不理解,不懂的地方,看来要再多几遍相关资料。
 
to 楼上的楼上的FW:
只要DBPROP_COMMITPRESERVE=true,则事务提交/或者回滚后行集仍然是可用的(preserved).
但是在使用服务器游标时,DBPROP_COMMITPRESERVE属性(实际上就是ADO原生对象的
'Preserve on Commit'属性)是无法更改的!!!
 
to oceanwave,
.我说的只是局域网.不会有人会在B/S结构中使用服务器端游标吧:p

另:
CacheSize在客户端游标是可以用的,需要设置LockType:= ltBatchOptimistic;
 
再次质疑CacheSize:
---------------------------------------------------------------
ADOQuery的属性设置如下:
CursorLocation:= clUseClient;
CursorType:= ctKeySet;
LockType:= ltBatchOptimistic;
CacheSize:= 100;
SQL.Text:= 'Select * from companys';
MaxRecords:= 0;

companys表有一万条测试记录.
adoquery.open后程序占34兆内存,设定
MaxRecords:= 100;
再次adoquery.open后程序只占有8兆内存.

很显然在这里CacheSize没有起到任何作用,所有的记录仍然全部被缓存到
本机.

测试环境:
Win2000Pro, D6,ADO2.7,SQL SERVER 2K.
---------------------------------------------------------------
 
oracle ado 服务器游标 不行的说
 
现在我用
ADOConnection.Execute('Begin Transaction',cmdText,[]);
ADOConnection.Execute('Commit Transaction',cmdText,[]);
ADOConnection.Execute('Rollback Transaction',cmdText,[]);
来代替
ADOConnection.BeginTrans;
ADOConnection.CommitTrans;
ADOConnection.Rollback;

挺好的!
 
顶部