ADO speed up to open table access

2019-08-07 20:20发布

问题:

What is the best method to open a table with ADO and Access, for rs.AddNew and rs.Update, based on the speed for writing data?

Do I need to use a particular cursor or a particular method?

I use an ADO connection to Jet from VB6.

回答1:

My two suggestions would be:

  1. Open the Recordset as adOpenStatic to minimize the overhead of trying to keep track of changes to the table that might be made by other users.

  2. Wrap multiple .AddNew operations in a transaction by doing cn.BeginTrans before the batch of inserts, and cn.CommitTrans afterwards.

Edit

In response to the comment from @Bob77, in which he said:

Throwing Begin/End Trans around a series of arbitrary update operations doesn't provide any intrinsic performance benefit, and in most cases should make matters worse.

The following VBScript test results clearly show that wrapping a batch of insertions in a Transaction can greatly improve performance when working with Jet/ACE databases.

Option Explicit
Dim con, rst, t0, i, n, s
Const adUseClient = 3
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const useTransaction = False

t0 = Timer
n = 1000
Set con = CreateObject("ADODB.Connection")
con.CursorLocation = adUseClient
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Y:\adoTimeTest.accdb;"
Set rst = CreateObject("ADODB.Recordset")
rst.Open "SELECT * FROM tbl", con, adOpenStatic, adLockOptimistic
If useTransaction Then
    con.BeginTrans
End If
For i = 1 to n
    rst.AddNew
    rst("ItemName").Value = "Item_" & i
    rst("SeqNo").Value = i
    rst.Update
Next
If useTransaction Then
    con.CommitTrans
End If
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
s = "Added " & n & " rows in " & Round(Timer - t0, 1) & " seconds with"
If Not useTransaction Then
    s = s & "out"
End If
s = s & " transaction."
Wscript.Echo s

The structure of the table [tbl] is

ID       - AutoNumber, Primary Key
ItemName - Text(255), Indexed (duplicates OK)
SeqNo    - Long Integer, Indexed (no duplicates)

Test 1: useTransaction = False

The [tbl] table is empty and the .addcb file has been freshly compacted.

Y:\>cscript /nologo adoTimeTest.vbs
Added 1000 rows in 103.9 seconds without transaction.

Test 2: useTransaction = True

The [tbl] table has been emptied and the .addcb file has been freshly compacted again.

Y:\>cscript /nologo adoTimeTest.vbs
Added 1000 rows in 4.9 seconds with transaction.

Edit

In response to the follow-up comment from @Bob77:

I'd try again opening the database for exclusive access.

Additional tests using ODBC and Exclusive access:

con.Open "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=Y:\adoTimeTest.accdb;Exclusive=1;Uid=admin;Pwd=;"

Test 3: useTransaction = False

The [tbl] table is empty and the .addcb file has been freshly compacted.

Y:\>cscript /nologo adoTimeTest.vbs
Added 1000 rows in 26.5 seconds without transaction.

Test 4: useTransaction = True

The [tbl] table has been emptied and the .addcb file has been freshly compacted again.

Y:\>cscript /nologo adoTimeTest.vbs
Added 1000 rows in 6.1 seconds with transaction.