我有以下代码从SQL Server 2008访问记录集。
Dim cnn As Object
Dim rs As Object
Dim strSQL As String
Set cnn = CreateObject("ADODB.Connection") 'ADO Connection
cnn.ConnectionString = "DRIVER=SQL Server;SERVER=" & dbServer & ";" & _
"Trusted_Connection=Yes;DATABASE=" & dbDatabase
cnn.Open
strSQL = "Select * from mytable"
Set rs = CreateObject("ADODB.Recordset")
rs.Open strSQL, cnn, adOpenKeyset, adLockOptimistic
在rs.Open
上,需要1秒到3秒。有没有更快的方式来访问记录集?
变量dbServer和dbDatabase在模块中定义为常量字符串。
答案 0 :(得分:3)
您有2个操作:
延迟在哪里?
您可以在两个打开的语句之前添加Debug.Print Now()
行,在记录集打开之后添加另一行。
如果打开连接是瓶颈,请查看使用本机客户端提供程序是否可以加快速度。 www.connectionstrings.com: SQL Server Native Client 10.0 OLE DB Provider
如果打开记录集是瓶颈,您有几个选择。如果您实际上不需要动态/可编辑记录集,请使用adOpenStatic而不是adOpenKeyset。您可以尝试CommandTypeEnum adCmdTable来打开表,而不是使用返回所有内容的SELECT语句。或者使用SELECT语句,包括显式字段列表而不是“*”...因为“*”需要额外访问服务器以确定它代表哪些字段。 (虽然这可能不是一个很大的瓶颈。)您还可以尝试使用WHERE子句根据主键值选择单个记录。
答案 1 :(得分:3)
假设mytable
是基表而不是VIEW,SQL尽可能简单,即没有优化的余地。
如果要将整个表格内容放在VBA代码中进行进一步的RBAR(“通过痛苦的行”= pejorative)处理,那么考虑使用更复杂的SQL将过程逻辑重写为“基于集合”的范例,例如:添加WHERE
条款将是一个良好的开端。
如果您确实需要将整个表格内容放在一起并且表格相对较大,则需要相对较长的时间。同样,您的代码中没有用于优化的范围。
您当前正在执行同步提取,这意味着您的VBA代码的执行将在rs.Open
行等待,直到提取完成为止。对您的用户的影响将是应用程序显示为冻结,可能已崩溃。
另一种方法是使用异步提取。重新定位您的代码类模块,将记录集声明为WIthEvents
(需要重新定位到模块级别)并在打开它之前在记录集上指定adAsyncFetch
选项(您可能需要稍微改变您的方法以适应这个)。一旦发送请求,这将导致执行继续超过rs.Open
(因此您需要将关闭连接/记录集的任何代码重新定位到单独的子过程)。然后,您可以使用FetchProgress
和FetchComplete
事件向应用程序中的最终用户提供反馈。有关详细信息,请参阅this MSDN article。
我从来没有能够从Access引擎/提供程序中获得任何有意义的“完成百分比”样式进度。但是,您至少可以向用户显示一个选取框样式进度条,以向他们保证数据正在被提取。他们仍然可以与UI进行交互(例如点击控件),并确保应用程序没有崩溃。