我想从xml文件导入大约9.000.000行到MySql服务器。目前我要逐行插入数据,这非常慢。我能够上传大约50行/秒,这意味着它需要数天才能完成。对于另一个项目,我将类似的数据一次加载到一个包含5000行的数据表中,然后我将一次批量插入所有5000行。这使我达到约7.500行/秒。问题在于SQL服务器,这就是MySQL。我无法从数据表中找到任何使用MySqlBulkLoader类的人。这有可能吗?我将如何去做呢?
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")
答案 0 :(得分:1)
这将从XML中读取一百万行,提取数据的子集,导出为CSV(使用CSVHelper),然后使用中的MySqlBulkLoader
将其加载到MySql大约30秒。
' 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()
临时步骤花了9秒从XML中选择部分,15秒写入CSV,7秒用于MySQL加载数据。
您的XML文件的细节是个谜(在发布之后,该链接已被添加到问题中)。由于您可以将其加载到DataTable
,因此测试只使用了myDT.WriteXml(...)
的结果,因此您可能需要更改该部分。将其保留为linq查询,让CSVHelper
使用它,因为applet本身根本不需要收集数据。
唯一的"技巧"是格式化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
只是一个显示属性的类,它是较大XML数据中的所需列。它的作用是:a)尽快删除你不需要/想要的无关列; b)提供'持有者'用于CSVHelper的数据。
答案还使用内置的MySqlBulkLoader
工具,我发现它比SQL LOAD DATA LOCAL INFILE
表单更容易使用。