2017-06-07 15 views
0

XMLファイルを含むzipファイルを読み取るVB.Netアプリケーションがあります。私はXMLファイルを行セグメントに解析し、アプリケーションIDとして1つのノード値を取り出し、それをMS SQLデータベースに送信する必要があります。 XMLファイルは次のようになります。できるだけ早くXMLを解析する

<?xml version="1.0" encoding="UTF-8"?> 
<PROJECTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<row> 
<APPLICATION_ID>9243987</APPLICATION_ID> 
<ACTIVITY>P30</ACTIVITY> 
<ADMINISTERING_IC>AR</ADMINISTERING_IC> 
<APPLICATION_TYPE>5</APPLICATION_TYPE> 
<ARRA_FUNDED>N</ARRA_FUNDED> 
<AWARD_NOTICE_DATE>05/22/2017</AWARD_NOTICE_DATE> 
<BUDGET_START>04/01/2017</BUDGET_START> 
</row> 
<row> 
<APPLICATION_ID>9243988</APPLICATION_ID> 
<ACTIVITY>P30</ACTIVITY> 
<ADMINISTERING_IC>AR</ADMINISTERING_IC> 
<APPLICATION_TYPE>5</APPLICATION_TYPE> 
<ARRA_FUNDED>N</ARRA_FUNDED> 
<AWARD_NOTICE_DATE>05/22/2017</AWARD_NOTICE_DATE> 
<BUDGET_START>04/01/2017</BUDGET_START> 
</row> 
<row> 
<APPLICATION_ID>9243989</APPLICATION_ID> 
<ACTIVITY>P30</ACTIVITY> 
<ADMINISTERING_IC>AR</ADMINISTERING_IC> 
<APPLICATION_TYPE>5</APPLICATION_TYPE> 
<ARRA_FUNDED>N</ARRA_FUNDED> 
<AWARD_NOTICE_DATE>05/22/2017</AWARD_NOTICE_DATE> 
<BUDGET_START>04/01/2017</BUDGET_START> 
</row> 
</PROJECTS> 

このファイルには100万レコードが含まれ、サイズは100mgに近い可能性があります。私の現在のコードは下にあり、100万レコードを実行するのに8時間もかかることがあります。

ファイルを解析し、私のVBのコードは次のとおりです。

  If ofdXML.ShowDialog <> Windows.Forms.DialogResult.Cancel Then 
      stopWatch.Start() 
      Dim result As String 
      Dim fName As String = ofdXML.FileName 
      If fName.EndsWith("zip") Then 
       Dim ePath As String = "E:\Downloads\WEEKLY" 
       fileName = ExtractArchive(fName, ePath) 
       fName = Path.Combine(ePath, fileName) 
      End If 

      result = Path.GetFileNameWithoutExtension(fName) 
      Dim rdr As New StreamReader(fName) 
      While (rdr.Peek >= 0) 
       varLine = rdr.ReadLine 
       sTag = varLine.Contains("<row>") 
       eTag = varLine.Contains("</row>") 
       If sTag And eTag Then 
        appLine = varLine 
        If appLine.Contains("<row><APPLICATION_ID>") Then 
         appID = appLine.Substring(Len("<row><APPLICATION_ID>"), appLine.IndexOf("/APPLICATION_ID") - Len("<row><APPLICATION_ID>") - 1) 
        End If 
       ElseIf sTag Then 
        v1 = True 
        appLine = varLine 
        If appLine.Contains("<row><APPLICATION_ID>") Then 
         appID = appLine.Substring(Len("<row><APPLICATION_ID>"), appLine.IndexOf("/APPLICATION_ID") - Len("<row><APPLICATION_ID>") - 1) 
        End If 
       ElseIf eTag Then 
        appLine = appLine & varLine 
        v1 = False 
       ElseIf v1 Then 
        appLine = appLine & varLine 
        If appLine.Contains("<APPLICATION_ID>") Then 
         Dim xi As Integer = appLine.IndexOf("_ID>") + 4 
         appID = appLine.Substring(xi, appLine.IndexOf("/APPLICATION_ID") - (xi + 1)) 
        End If 
       End If 


       If Trim(Len(varLine)) > 0 And appLine.Contains("<row>") And appLine.Contains("</row") And Not varLine.Contains("</PROJECTS>") Then 
        TextBox2.Text = i.ToString 
        TextBox3.Text = appID 
        sb.Append(appID + ",") 
        Application.DoEvents() 
        i += 1 
        ADMIN_Save_To_Database(appLine, appID, result) 
       End If 
      End While 

     End If 

すべてのヘルプは大歓迎です。

+0

MicrosoftのXML解析ツールは、はるかに高速になります実行方法を知ってもらおう

 Dim rdr As New StreamReader(fName) Dim xml As New XmlDocument() xml.Load(rdr) Dim DocumentNodes As XmlNodeList = xml.GetElementsByTagName("row") For Each xn As XmlNode In DocumentNodes Dim example As XmlNode = xn.SelectSingleNode("APPLICATION_ID") If example IsNot Nothing Then Dim applicationID As String = example.InnerText ADMIN_Save_AuthoringNames(xn.InnerXml, applicationID, result) End If Next 

。 [チェックアウト](https://msdn.microsoft.com/en-us/library/dc0c9ekk(v=vs.110).aspx?cs-save-lang = 1&cs-lang = vb#code-snippet-2 )を使用すると、このルートに行く場合は、「title」を「Application_ID」に置き換えることができます。 –

+0

できるだけ速くしたい場合は、[bulk import](https://docs.microsoft.com/en-us/sql/relational-databases/import-export/examples-of-bulk-import-and-export)を使用してください。 -of-xml-documents-sql-server)を使用します。 –

+0

マルチスレッド化やタスクの作成... – Codexer

答えて

0

私はにコードを変更しました:私はあなたがそれを

+1

上記のコードを使用して私は約2時間に時間を削減できましたが、BCPの上のコードを使用して2分未満になりました。私の最大のボトルネックは、各レコードをデータベースに保存していたようです。みんなありがとう – user1314159

0

実際のXML解析を調べることをお勧めします。あなたが問い合わせることができるDOMやSAXを聞くことができます。特定のタグだけに興味があるので、そのタグのSAXリスナーを設定して、他のものはすべて無視してください。

これはあなたが始める必要があります。

https://www.tutorialspoint.com/vb.net/vb.net_xml_processing.htm

を使用すると、最適化のための外観を解析し、あなたの文字列にこだわっを主張した場合。ループはキラーです!ループ内で高価なものをやりたくない場合は、ループ内で高価なものをやりたいとは思わない。

たとえば、「<行> < APPLICATION_ID>」の長さは、すべての行(フォーマットに応じて)で2回計算します。だけでなく、高価ですが、結果は定数です!ループの外側で一度設定または計算します。

すべての.Contains()呼び出しは非常に高価です。あなたの多くは冗長です。たとえば、ループの最上部付近に「<行>」と「< /行>」が存在するかどうかを確認してから、ループの最後付近で再度実行します。

つまり、XML解析ツールが最適です。それをやりたくない場合は、ループの外側から抜くか、毎回1回だけ実行するという高価な操作については、コードを慎重に見てください。

関連する問題