使用ADO.NET / OleDb将非常慢的记录插入到Jet数据库中

时间:2010-12-27 03:00:36

标签: performance ado.net oledb jet

我正在尝试通过ADO.NET / OleDb将大量记录插入到Jet(Access)数据库中。它运行缓慢。缓慢主要是由于DbDataAdapter.Update方法。用微软的话来说,

  

...这些陈述不是作为批处理执行的;每行都单独更新。

这是一个真正的WTF,因为我的数据库应用程序的性能比使用旧的ADO或DAO(带有AddNew / Update循环的Recordset)的VB6中的等效代码慢约30倍。

SqlClient提供程序具有SqlBulkCopy类; OleDb有什么相同的东西吗?

即使能够更改其写入缓存行为也可能有所帮助。 (即插入每一行后不要刷新缓存!)

我有什么可以做的,或者ADO.NET刚刚为Jet打破了吗?

* 编辑添加:这是我的代码的缩减版本,使用缩减测试数据库。

首先,VBA / ADO版本(Access 2003):

Dim con As ADODB.Connection
Set con = CurrentProject.Connection
con.Execute "DELETE * FROM tblTest", , adCmdText Or adExecuteNoRecords
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.Open "tblTest", con, , adLockPessimistic
Dim i&, t!
t = Timer
For i = 1 To 10000
    rs.AddNew
    rs!mainKey = i
    rs!testColumn = Rnd * 100
    rs.Update
Next
rs.Close
Debug.Print "time to add 10000 (by ADO) " & Timer - t

输出:time to add 10000 (by ADO) 0.296875

现在是ADO.NET版本(VB.NET 2010):

Dim sProvider As String = "PROVIDER = Microsoft.Jet.OLEDB.4.0;"
Dim sDataSource As String = "Data Source = 'C:\test.mdb'"
Dim connection As New OleDbConnection(sProvider & sDataSource)
connection.Open()
Dim q As New OleDbCommand("DELETE * FROM tblTest", connection)
q.ExecuteNonQuery()
Dim ds As New DataSet
Dim selectCmd As OleDbCommand = connection.CreateCommand()
selectCmd.CommandText = "SELECT * FROM tblTest"
Dim da As New OleDbDataAdapter(selectCmd)
da.Fill(ds, "tblTest")
Dim theTable As DataTable = ds.Tables("tblTest")
For i As Integer = 1 To 10000
    Dim row = theTable.NewRow()
    row.Item("mainKey") = i
    row.Item("testColumn") = Rnd() * 100
    theTable.Rows.Add(row)
Next i
Dim t! : t = Microsoft.VisualBasic.Timer
Dim cb As New OleDbCommandBuilder(da)
da.Update(ds, "tblTest")
Debug.Print("time to add 10000 (by ADO.NET): " & Microsoft.VisualBasic.Timer - t)
connection.Close()

输出:time to add 10000 (by ADO.NET): 5.859375

3 个答案:

答案 0 :(得分:1)

确保在调用方法时打开连接。如果在调用更新方法之前关闭连接(我实际上在某些示例代码中看到了这种情况),则更新方法可能会尝试以非最佳方式打开连接。 如果没有连接,则在Jet中打开连接可能会非常慢。您可能需要添加OLE DB SERVICES = -1以确保连接已合并。

答案 1 :(得分:0)

答案 2 :(得分:0)

您是否真的尝试使用随机值填充表格?如果是这样,有更快的方法(使用基于现有表的INSERT,或在您要附加的表上,因此您可以多次运行它并快速达到所需记录的数量)。

通常,SQL INSERT比一次添加一条记录要快一个数量级。如果你必须按照你的方式去做,那么你可能会考虑是否可以通过ADO / ADO.NET使用Jet / ACE事务。我不知道这是否可用。如果不是,并假设COM是一个选项,你应该考虑只使用DAO,这样你就可以使用Jet / ACE事务,这会将写入延迟到最后(比如发布一个批处理)。

我不是ADO maven,但我还是经常在Classic ADO中有一些批处理函数,所以你也可以考虑调查它。