MS Access: Perché è così ADODB.Recordset.BatchUpdate molto più lento di Application.ImportXML?
-
24-10-2019 - |
Domanda
Sto cercando di eseguire il codice qui sotto per inserire un sacco di dischi (da un file con un formato di file strano) nel mio database Access 2003 da VBA. Dopo molti, molti esperimenti, questo codice è il più veloce che ho potuto venire con: lo fa 10000 record in circa 15 secondi sulla mia macchina. Almeno 14,5 di quei secondi (es. Quasi tutto il tempo) è in singola chiamata a UpdateBatch.
Ho letto altrove che il motore Jet non supporta UpdateBatch. Così forse c'è un modo migliore per farlo.
Ora, vorrei solo pensare il motore JET è semplice lento, ma che non può essere così. Dopo aver generato la tabella 'irascibile' con il codice qui sotto, ho ragione cliccato su, preso Export, e salvato in formato XML. Poi ho cliccato destra, raccolte di importazione, e ricaricato l'XML. Tempo totale di importare il file XML? Meno di un secondo, cioè. almeno 15x più veloce.
Sicuramente c'è un modo efficace per inserire i dati in Access che non richiede la scrittura di un file temporaneo?
Sub TestBatchUpdate()
CurrentDb.Execute "create table testy (x int, y int)"
Dim rs As New ADODB.Recordset
rs.CursorLocation = adUseServer
rs.Open "testy", CurrentProject.AccessConnection, _
adOpenStatic, adLockBatchOptimistic, adCmdTableDirect
Dim n, v
n = Array(0, 1)
v = Array(50, 55)
Debug.Print "starting loop", Time
For i = 1 To 10000
rs.AddNew n, v
Next i
Debug.Print "done loop", Time
rs.UpdateBatch
Debug.Print "done update", Time
CurrentDb.Execute "drop table testy"
End Sub
I sarebbe disposto a ricorrere a C / C ++, se c'è qualche API che mi permetta di fare inserti veloci in quel modo. Ma io non riesco a trovarlo. Non può essere che Application.ImportXML sta usando le API non documentate, può?
Soluzione
A meno che non si deve fare questo con ADO, tenta invece DAO. Qui ci sono i tempi sul mio portatile con la vostra procedura e una versione di DAO:
ADO:
starting loop 9:51:59 PM
done loop 9:52:00 PM
done update 9:52:54 PM
DAO:
starting loop 9:58:29 PM
done loop 9:58:31 PM
done update 9:58:31 PM
Questa è la versione DAO che ho usato.
Sub TestBatchUpdateDAO()
CurrentDb.Execute "create table testy (x int, y int)"
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("testy", dbOpenTable, dbAppendOnly)
Dim i As Long
Debug.Print "starting loop", Time
For i = 1 To 10000
rs.AddNew
rs!x = 50
rs!y = 55
rs.Update
Next i
Debug.Print "done loop", Time
'rs.UpdateBatch '
Debug.Print "done update", Time
rs.Close
Set rs = Nothing
CurrentDb.Execute "drop table testy"
End Sub