VBA:更快的Recordset连接

时间:2011-10-17 15:47:00

标签: ms-access vba

我有以下代码从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在模块中定义为常量字符串。

2 个答案:

答案 0 :(得分:3)

您有2个操作:

  1. 打开连接
  2. 使用该连接打开记录集
  3. 延迟在哪里?

    您可以在两个打开的语句之前添加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(因此您需要将关闭连接/记录集的任何代码重新定位到单独的子过程)。然后,您可以使用FetchProgressFetchComplete事件向应用程序中的最终用户提供反馈。有关详细信息,请参阅this MSDN article

我从来没有能够从Access引擎/提供程序中获得任何有意义的“完成百分比”样式进度。但是,您至少可以向用户显示一个选取框样式进度条,以向他们保证数据正在被提取。他们仍然可以与UI进行交互(例如点击控件),并确保应用程序没有崩溃。