MS Access: ¿Por qué es ADODB.RecordSet.BatchUpdate mucho más lento que Application.ImportXML?
-
24-10-2019 - |
Pregunta
Estoy tratando de ejecutar el código a continuación para insertar muchos registros (de un archivo con un formato de archivo extraño) en mi base de datos Access 2003 desde VBA. Después de muchos, muchos experimentos, este código es el más rápido que he podido encontrar: hace 10000 registros en aproximadamente 15 segundos en mi máquina. Al menos 14.5 de esos segundos (es decir, casi todo el tiempo) está en la llamada única a UpdateBatch.
He leído en otra parte que el motor a reacción no es compatible con UpdateBatch. Entonces, tal vez hay una mejor manera de hacerlo.
Ahora, pensaría que el motor a reacción es simple, pero eso no puede ser. Después de generar la tabla 'testosa' con el siguiente código, lo hice clic derecho, elegí la exportación y la guardé como XML. Luego hice clic derecho, elegí la importación y recargué el XML. ¿Tiempo total para importar el archivo XML? Menos de un segundo, es decir. al menos 15 veces más rápido.
¿Seguramente hay una forma eficiente de insertar datos en el acceso que no requiere escribir un archivo TEMP?
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
Estaría dispuesto a recurrir a C/C ++ si hay alguna API que me permita hacer insertos rápidos de esa manera. Pero parece que no puedo encontrarlo. No puede ser esa aplicación. ImportXML está usando API indocumentadas, ¿verdad?
Solución
A menos que deba hacer esto con ADO, pruebe DAO en su lugar. Aquí están los tiempos en mi computadora portátil con su procedimiento y una versión 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
Esta es la versión DAO que usé.
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