|
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件 ★ 免费下载 ★ ★ 使用帮助★
本帖最后由 hehex 于 2014-3-11 15:32 编辑
zhaogang1960 发表于 2014-3-11 14:03
程序3:仅连接数据库,什么也不操作,速度比程序1有查询慢很多
记得循环连接前重新实例化连接对象即可 ...
综合了赵版和郝版以及上面几位网友的意见说说个人浅见:
修改了赵老师和郝版给的测试程序,用个一个52个元素的定长一维Double 数组来记录每次打开Connection 和生成游标的时间。其实就是把郝版的那个代码每次不debug.print 出来而是写到数组内。最后分别输出到一个新的工作表Sheet1 的3列内。
得到的测试数据发现,在未定义rs 变量时,就是第一次建立Connection 连接时,系统的时间是几乎相同的。
我们知道当ADO 对象建立Connect 连接时是要在堆内存(heap) 中开辟一片区域,用于存储当前连接数据表的数据,而且从理论上来说
Set rs = cnn.Execute(SQL)
arr = rs.GetRows
应该占有系统时间及开销,但是从测试数据上几乎看不到分别,上一个帖子没名字网友的截图也说明了这一点。
那么就从现象上说明了一个问题:主要的时间开销来自ADO 对象Connection 操作,我们想想也是,连接数据表要有硬件IO,去硬盘上读取。
那么我们就主要认为是Connection 消耗了时间,其他操作暂时忽略掉时间的消耗。
然后从第2次循环就发生有意思的事情了:
没有指定rs 变量的再进行Connection 操作时速度变慢,慢出接近一倍,在我的机器上是0.04 秒接近到0.09 秒,然后每次进行Connection
基本都是这个速度。
而指定了rs 引用变量的程序呢,在Connection时速度不减反增,只用了没有指定的1/3 的时间。这是为什么呢?
在微软没有公开ADO 内存使用的详细解释之前,我只能做一下臆测:
首先rs 是什么? rs 是一个分配在Stack(栈区) 的引用变量,里面装的是RecordSet 这个实体数据集的引用。可能C,C++ 的开发者喜欢叫它指针,
总之通过rs 才可以访问到这个数据集。而RecordSet 是一个数据表的索引集,是根据SQL 语句生成的一个索引集。(这个我查了很久资料)是不能独立于
Connection 存在的,(这个我已经写程序测试过)那么我们可以认为,其实RecordSet 里面也只是一些索引,而得出的数据实体物理内存是装在Connection 里面的。
那么rs 就有点指针的指针的意思了。
那么RecordSet 对象存储在内存哪里呢?是堆内存(heap) 还是数据区开辟的缓存中呢?微软没有公布技术细节,我们无从得知。
我们仅仅从现象上知道的是开辟了RecordSet 的之后再打开Connection 速度会变快,否则变慢。
上面我说过了自己的观点,rs 变量是一个引用或者说是一个指针,只有通过这个保存的变量才能访问到RecordSet 实体,如果Conn.Execute(sql) 这么过去了,
返回值其实没有保留(被系统自动丢弃了),那么就是说虽然开辟了这个索引区域,而程序却无法访问到了,再下一次循环时该区域丢掉了(其实物理内存中还在,但是无法访问)。等于没开。
至于为什么开辟了RecordSet 连接其他数据表的Connection 方法速度就会变快,查了半天资料,去CSDN 问了半天,还是没得到确切的答案。只是从现象中看确实是这样,
是否是编译器,解释器优化的结果我们不清楚,也许是某些复杂的内存指针操作呢。微软一天不彻底公开所有细节,所有答案只能是猜测。
附件是我的测试程序,思想完全来自赵老师和郝版。
|
|