【发布时间】:2017-05-31 13:37:03
【问题描述】:
我最终尝试使用SqlBulkCopy 将文件中的行插入到 SQL Server 数据库中。我的代码如下。
当我尝试向数据表中添加太多行时,就会出现问题。我不确定限制是多少,但我的文件有 500 万行,并且我得到了一个 OutOfMemoryException 就行了:
newRow.ItemArray = objFields.ToArray()
所以我认为这与数据表的限制有关。
有没有一种方法可以逐步添加行并一次插入一些行,或者我在这里做错了什么可以更改?
这个过程确实适用于较小的文件。
谢谢
Public Sub bulk_insert(file_name, delimiter, table_name)
' create a data table from the file
' ---------------------------------
Dim lines = IO.File.ReadAllLines(file_name)
Dim tbl = New DataTable
Dim colCount = lines.First.Split(delimiter).Length
' add the correct number of columns to the table
' ----------------------------------------------
For i As Int32 = 1 To colCount
tbl.Columns.Add(New DataColumn("Column_" & i, GetType(String)))
Next
' add the lines to the data table
' -------------------------------
For Each line In lines
Dim objFields = From field In line.Split(delimiter) Select CType(field, Object)
Dim newRow = tbl.Rows.Add()
newRow.ItemArray = objFields.ToArray()
Next
' create a connection to the database
' -----------------------------------
Dim myConn = New SqlConnection(Main.this_page.sql_connection_string)
' start the Bulk Copy
Dim SqlBulkCopy = New SqlBulkCopy(myConn)
SqlBulkCopy.BatchSize = 10000
SqlBulkCopy.BulkCopyTimeout = 10000
' open the connection
' -------------------
myConn.Open()
' perform the copy
' ----------------
SqlBulkCopy.DestinationTableName = table_name
SqlBulkCopy.WriteToServer(tbl)
' cloe the connection
' -------------------
myConn.Close()
End Sub
编辑:经过测试发现报错时,行数为2097152
编辑:由于我不想回答我自己的问题,也无法将其放在评论中,因此我根据以下 the_lotus 提供的答案将我的结果包含在下面。下面的代码解决了这个问题:
Public Sub bulk_insert(file_name, delimiter, table_name)
' create a connection to the database
' -----------------------------------
Dim myConn = New SqlConnection(Main.this_page.sql_connection_string)
' open the connection
' -------------------
myConn.Open()
' create a data table from the file
' ---------------------------------
Dim lines = IO.File.ReadAllLines(file_name)
Dim tbl = New DataTable
Dim colCount = lines.First.Split(delimiter).Length
' add the correct number of columns to the table
' ----------------------------------------------
For i As Int32 = 1 To colCount
tbl.Columns.Add(New DataColumn("Column_" & i, GetType(String)))
Next
Dim x As Integer = 0
While x < lines.Count - 1
' clear the data table
' --------------------
tbl.Clear()
' add the lines to the data table in 1M row increments
' ---------------------------------------------------
If x + 1000000 > lines.Count - 1 Then
For y = x To lines.Count - 1
Dim objFields = From field In lines(y).Split(delimiter) Select CType(field, Object)
Dim newRow = tbl.Rows.Add()
newRow.ItemArray = objFields.ToArray()
Next
x = lines.Count - 1
Else
For y = x To x + 1000000
Dim objFields = From field In lines(y).Split(delimiter) Select CType(field, Object)
Dim newRow = tbl.Rows.Add()
newRow.ItemArray = objFields.ToArray()
Next
x += 1000000
End If
' start the Bulk Copy
Dim SqlBulkCopy = New SqlBulkCopy(myConn)
SqlBulkCopy.BatchSize = 1000000
SqlBulkCopy.BulkCopyTimeout = 1000
' perform the copy
' ----------------
SqlBulkCopy.DestinationTableName = table_name
SqlBulkCopy.WriteToServer(tbl)
End While
' cloe the connection
' -------------------
myConn.Close()
End Sub
【问题讨论】:
-
你自己回答了你的问题......加载前 100 个然后做你的东西,然后加载下一个 100 等等
-
但是如何释放内存呢?
-
数据表限制为 160 亿行(但这可能基于单个 int 列)。一个问题是您还将整个文件读入内存。使用类似 CSVHelper 的库
-
你知道什么是内存吗? webopedia.com/TERM/R/RAM.html 内存是磨损数据存储在您的计算机内存有限且仅分配给您的应用程序的一定数量,因此加载超过 500 万行数据您的计算机无法处理使用那么多内存.. 想想看就像一小杯水。你不能在里面装1L。但是你可以装 50 毫升喝下去,再装 50 毫升喝到 1 升
-
对这个任务使用 DataTable 是错误的方法。 DataTable 所做的只是为 SqlBulkCopy 实例提供一个IDataReader。编写自己的 IDataReader 实现来解析文件并将数据提供给 SqlBulkCopy 会更好地为您服务。
标签: sql-server vb.net datatable