DataTable 中的 MySqlBulkLoader - VB.net
MySqlBulkLoader from DataTable - VB.net
我想将大约 9.000.000 行从 xml 文件导入到 MySql 服务器。目前我正在逐行插入数据,这非常慢。我每秒可以上传大约 50 行,这意味着需要几天才能完成。对于另一个项目,我一次将类似的数据加载到一个包含 5000 行的数据 table 中,然后我将一次批量插入所有 5000 行。这使我达到了大约 7.500 行/秒。问题是 SQL 服务器,这是 MySQL。我无法从数据 table 中找到任何使用 MySqlBulkLoader class 的人。这可能吗?我该怎么做?
xml 文件中前 750 个元素的示例:http://view.qrdetector.dk/test.xml
这些是我在 xml 文件的数据库中需要的列。
'Create datatable to hold the information from the XML file
Dim ReadXML_DT As New DataTable
ReadXML_DT.Columns.Add("KoeretoejIdent", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejArtNavn", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejAnvendelseNavn", GetType(String))
ReadXML_DT.Columns.Add("RegistreringNummerNummer", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejOplysningStatus", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejOplysningFoersteRegistreringDato", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejOplysningStelNummer", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejMaerkeTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejModelTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejVariantTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("DrivkraftTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("SynResultatSynsType", GetType(String))
ReadXML_DT.Columns.Add("SynResultatSynsDato", GetType(String))
ReadXML_DT.Columns.Add("SynResultatSynStatusDato", GetType(String))
ReadXML_DT.Columns.Add("SidsteSynTjek", GetType(String))
我手动制作了一个包含 130.000 行的 CSV 文件,其中包含我需要的 15 列。然后我使用了 Plutonix 回复中的批量插入代码。我现在能够在大约 215 秒内解析 130.000 行,这使我的平均速度约为 600 行/秒。这与之前的结果几乎相同。这是因为我连接到 MySQL 服务器吗?
Dim sw As Stopwatch = New Stopwatch
sw.Start()
' Finally, BulkLoad
Dim cols As String() = {"KoeretoejIdent", "KoeretoejArtNavn", "KoeretoejAnvendelseNavn", "RegistreringNummerNummer", "KoeretoejOplysningStatus", "KoeretoejOplysningFoersteRegistreringDato", "KoeretoejOplysningStelNummer", "KoeretoejMaerkeTypeNavn", "KoeretoejModelTypeNavn", "KoeretoejVariantTypeNavn", "DrivkraftTypeNavn", "SynResultatSynsType", "SynResultatSynsDato", "SynResultatSynStatusDato", "SidsteSynTjek"}
Dim rows As Integer = 0
Using dbcon As New MySqlConnection(connectionString)
Dim bulk = New MySqlBulkLoader(dbcon)
bulk.TableName = "synsbasen_testLoad"
bulk.FieldTerminator = "^"
bulk.LineTerminator = "\r\n" ' == CR/LF
bulk.FileName = "C:/Users/Synsbasen/Desktop/abc.csv" ' full file path name to CSV
bulk.NumberOfLinesToSkip = 1 ' has a header (default)
bulk.Columns.Clear()
For Each s In cols
bulk.Columns.Add(s) ' specify col order in file
Next
rows = bulk.Load()
End Using
sw.Stop()
' SW is a stopwatch
MsgBox(rows & "rows converted and loaded in " & sw.Elapsed.TotalSeconds & " secs")
这将从 XML 中读取 百万行 ,提取数据子集,导出为 CSV(使用 CSVHelper),然后将它们加载到 MySql 在 大约 30 秒 中使用 MySqlBulkLoader
。
' Ienumberable of the data parts to import
Dim recList As IEnumerable(Of SmSample)
' load some columns as a class
Using fs As FileStream = File.OpenRead(XMLFile)
Dim xDoc = XDocument.Load(fs)
' its IEnumberable - leave it that way
recList = xDoc.Descendants("Sample").
Select(Function(j) New SmSample With {.Name = j.Element("Name").Value,
.Descr = j.Element("Descr").Value,
.Price = Decimal.Parse(j.Element("Price").Value),
.ItemDate = DateTime.Parse(j.Element("ItemDate").Value)
}
)
End Using
' Have CSVHelper write them out
' this is the most time consuming part what with Disk IO and all
Using strW As New StreamWriter(CSVFile)
Using csv As New CsvWriter(strW)
' ToDo: add other things like Field sepatators etc
csv.Configuration.RegisterClassMap(Of SmSample.CSVItemMap)()
csv.WriteRecords(recList)
End Using
End Using
' Finally, BulkLoad
Dim cols As String() = {"Name", "Descr", "Price", "ItemDate"}
Dim rows As Int32 = 0
Using dbcon As New MySqlConnection(MySQLConnStr)
Dim bulk = New MySqlBulkLoader(dbcon)
bulk.TableName = "Sample"
bulk.FieldTerminator = ","
bulk.LineTerminator = "\r\n" ' == CR/LF
bulk.FileName = CSVFile ' full file path name to CSV
bulk.NumberOfLinesToSkip = 1 ' has a header (default)
bulk.Columns.Clear()
For Each s In cols
bulk.Columns.Add(s) ' specify col order in file
Next
rows = bulk.Load()
End Using
' SW is a stopwatch
Console.WriteLine("{0} rows converted and loaded in {1} secs",
rows, sw.ElapsedMilliseconds / 1000)
你的自然会花更长的时间,但 1,000,000 行已经有点大了,所以它应该足够适当地扩展。如果您想批量加载它们,请使用 500k 之类的东西。使用 Skip()
和 Take()
.
分部分编写 CSV 很容易
临时步骤 select 来自 XML 的部分花费了 9 秒,写入 CSV 花费了 15 秒,MySQL 加载数据花费了 7 秒。
你的 XML 文件的细节是个谜(link 是在发布后很好地添加到问题中的)。由于您可以将其加载到 DataTable
,测试仅使用了 myDT.WriteXml(...)
的结果,因此您可能需要更改该部分。将其保留为 linq 查询并让 CSVHelper
使用它,因为小程序本身根本不需要收集数据。
唯一的 "trick" 是格式化 DateTime
字段以便 MySQL 可以解析它:
Public Class CSVItemMap
Inherits CsvClassMap(Of SmSample)
Public Sub New()
AutoMap()
Map(Function(m) m.ItemDate).TypeConverterOption("yyyy-MM-dd")
End Sub
End Class
CSVHelper 非常酷,非常强大并且是结果不可或缺的一部分。
SmSample
只是一个 class,显示的属性是较大的 XML 数据中的所需列。它的作用是 a) 尽快摆脱你不 need/want 的无关列和 b) 提供 'holder' 数据供 CSVHelper 采取行动。
答案还使用了内置的 MySqlBulkLoader
工具,我发现它比 SQL LOAD DATA LOCAL INFILE
形式更容易使用。
我想将大约 9.000.000 行从 xml 文件导入到 MySql 服务器。目前我正在逐行插入数据,这非常慢。我每秒可以上传大约 50 行,这意味着需要几天才能完成。对于另一个项目,我一次将类似的数据加载到一个包含 5000 行的数据 table 中,然后我将一次批量插入所有 5000 行。这使我达到了大约 7.500 行/秒。问题是 SQL 服务器,这是 MySQL。我无法从数据 table 中找到任何使用 MySqlBulkLoader class 的人。这可能吗?我该怎么做?
xml 文件中前 750 个元素的示例:http://view.qrdetector.dk/test.xml
这些是我在 xml 文件的数据库中需要的列。
'Create datatable to hold the information from the XML file
Dim ReadXML_DT As New DataTable
ReadXML_DT.Columns.Add("KoeretoejIdent", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejArtNavn", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejAnvendelseNavn", GetType(String))
ReadXML_DT.Columns.Add("RegistreringNummerNummer", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejOplysningStatus", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejOplysningFoersteRegistreringDato", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejOplysningStelNummer", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejMaerkeTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejModelTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("KoeretoejVariantTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("DrivkraftTypeNavn", GetType(String))
ReadXML_DT.Columns.Add("SynResultatSynsType", GetType(String))
ReadXML_DT.Columns.Add("SynResultatSynsDato", GetType(String))
ReadXML_DT.Columns.Add("SynResultatSynStatusDato", GetType(String))
ReadXML_DT.Columns.Add("SidsteSynTjek", GetType(String))
我手动制作了一个包含 130.000 行的 CSV 文件,其中包含我需要的 15 列。然后我使用了 Plutonix 回复中的批量插入代码。我现在能够在大约 215 秒内解析 130.000 行,这使我的平均速度约为 600 行/秒。这与之前的结果几乎相同。这是因为我连接到 MySQL 服务器吗?
Dim sw As Stopwatch = New Stopwatch
sw.Start()
' Finally, BulkLoad
Dim cols As String() = {"KoeretoejIdent", "KoeretoejArtNavn", "KoeretoejAnvendelseNavn", "RegistreringNummerNummer", "KoeretoejOplysningStatus", "KoeretoejOplysningFoersteRegistreringDato", "KoeretoejOplysningStelNummer", "KoeretoejMaerkeTypeNavn", "KoeretoejModelTypeNavn", "KoeretoejVariantTypeNavn", "DrivkraftTypeNavn", "SynResultatSynsType", "SynResultatSynsDato", "SynResultatSynStatusDato", "SidsteSynTjek"}
Dim rows As Integer = 0
Using dbcon As New MySqlConnection(connectionString)
Dim bulk = New MySqlBulkLoader(dbcon)
bulk.TableName = "synsbasen_testLoad"
bulk.FieldTerminator = "^"
bulk.LineTerminator = "\r\n" ' == CR/LF
bulk.FileName = "C:/Users/Synsbasen/Desktop/abc.csv" ' full file path name to CSV
bulk.NumberOfLinesToSkip = 1 ' has a header (default)
bulk.Columns.Clear()
For Each s In cols
bulk.Columns.Add(s) ' specify col order in file
Next
rows = bulk.Load()
End Using
sw.Stop()
' SW is a stopwatch
MsgBox(rows & "rows converted and loaded in " & sw.Elapsed.TotalSeconds & " secs")
这将从 XML 中读取 百万行 ,提取数据子集,导出为 CSV(使用 CSVHelper),然后将它们加载到 MySql 在 大约 30 秒 中使用 MySqlBulkLoader
。
' Ienumberable of the data parts to import
Dim recList As IEnumerable(Of SmSample)
' load some columns as a class
Using fs As FileStream = File.OpenRead(XMLFile)
Dim xDoc = XDocument.Load(fs)
' its IEnumberable - leave it that way
recList = xDoc.Descendants("Sample").
Select(Function(j) New SmSample With {.Name = j.Element("Name").Value,
.Descr = j.Element("Descr").Value,
.Price = Decimal.Parse(j.Element("Price").Value),
.ItemDate = DateTime.Parse(j.Element("ItemDate").Value)
}
)
End Using
' Have CSVHelper write them out
' this is the most time consuming part what with Disk IO and all
Using strW As New StreamWriter(CSVFile)
Using csv As New CsvWriter(strW)
' ToDo: add other things like Field sepatators etc
csv.Configuration.RegisterClassMap(Of SmSample.CSVItemMap)()
csv.WriteRecords(recList)
End Using
End Using
' Finally, BulkLoad
Dim cols As String() = {"Name", "Descr", "Price", "ItemDate"}
Dim rows As Int32 = 0
Using dbcon As New MySqlConnection(MySQLConnStr)
Dim bulk = New MySqlBulkLoader(dbcon)
bulk.TableName = "Sample"
bulk.FieldTerminator = ","
bulk.LineTerminator = "\r\n" ' == CR/LF
bulk.FileName = CSVFile ' full file path name to CSV
bulk.NumberOfLinesToSkip = 1 ' has a header (default)
bulk.Columns.Clear()
For Each s In cols
bulk.Columns.Add(s) ' specify col order in file
Next
rows = bulk.Load()
End Using
' SW is a stopwatch
Console.WriteLine("{0} rows converted and loaded in {1} secs",
rows, sw.ElapsedMilliseconds / 1000)
你的自然会花更长的时间,但 1,000,000 行已经有点大了,所以它应该足够适当地扩展。如果您想批量加载它们,请使用 500k 之类的东西。使用 Skip()
和 Take()
.
临时步骤 select 来自 XML 的部分花费了 9 秒,写入 CSV 花费了 15 秒,MySQL 加载数据花费了 7 秒。
你的 XML 文件的细节是个谜(link 是在发布后很好地添加到问题中的)。由于您可以将其加载到 DataTable
,测试仅使用了 myDT.WriteXml(...)
的结果,因此您可能需要更改该部分。将其保留为 linq 查询并让 CSVHelper
使用它,因为小程序本身根本不需要收集数据。
唯一的 "trick" 是格式化 DateTime
字段以便 MySQL 可以解析它:
Public Class CSVItemMap
Inherits CsvClassMap(Of SmSample)
Public Sub New()
AutoMap()
Map(Function(m) m.ItemDate).TypeConverterOption("yyyy-MM-dd")
End Sub
End Class
CSVHelper 非常酷,非常强大并且是结果不可或缺的一部分。
SmSample
只是一个 class,显示的属性是较大的 XML 数据中的所需列。它的作用是 a) 尽快摆脱你不 need/want 的无关列和 b) 提供 'holder' 数据供 CSVHelper 采取行动。
答案还使用了内置的 MySqlBulkLoader
工具,我发现它比 SQL LOAD DATA LOCAL INFILE
形式更容易使用。