Access/VB: Performance in grossen XML-Dateien

03/03/2008 - 09:54 von Kurt Langeder | Report spam
Hallo NG!

Ich lese aus einer XML-Datei Werte aus und trage diese in eine
Access-Tabelle ein. Das funktioniert auch wunderbar. Hat die XML-Datei
jedoch eine gewisse Größe(ab ca. 7 MB), geht die Performance stark
zurück.

Mit einer Test-XML-Datei (ca. 50.000 Datensàtze), werden die ersten
1000 Datensàtze schnell innerhalb von 2 Sekunden eingelesen. Dann
nimmt die Dauer aber jeweils um mindestens 2 Sekunden zu - d.h. man
braucht dann schon 4 Sekunden für 1001 bis 2000 Datensàtze. 10
Sekunden für 2001 bis 3000 Datensàtze. 16 Sekunden für 3001 bis 4000
Datensàtze usw.

In div. Foren habe ich gelesen, dass das mit dem DOM-Objekt
zusammenhàngt, da dieses nicht für große XML-Strukturen ausgelegt ist,
da hier der gesamte Tree im Speicher gehalten wird. Als Alternative
wird dann immer SAX genannt. Ich konnte aber bis keinen einzige
brauchbaren Code im Netz finden.

Habe auch schon verschiedene MSXML-Versionen
("MSXML2.DOMDocument.3.0") und Parameter (z.B. xd.async = False,
xd.validateOnParse = False) probiert - hat aber alles nichts geholfen.

Die Datensàtze in der XML-Datei sehen etwa so aus:

<BEWEGUNG BewegungID="2007-11-12T07:26:50.641876" Kundennr="113899"
BuchDat="2007-10-01" BuchTxt="MUSTER JOHANN" BuchGrdlg="1000.00"
BuchSatz="20.00" BuchBetrag="200.00" WaehrungsCd="EUR"/>


Der VisualBasic-Code in Access:

Set xd = CreateObject("MSXML.DOMDocument")
xd.Load myXMLDatei
Set docroot = xd.documentElement
With docroot.childNodes
For iCount0 = 0 To .length - 1
anzAtributtes0 = .Item(iCount0).Attributes.length
For jCount0 = 0 To anzAtributtes0 - 1
xNodeName0 = .Item(iCount0).Attributes(jCount0).nodeName
xTEXT0 = .Item(iCount0).Attributes(jCount0).Text
'--> Wert in Tabelle eintragen
Next
usw.


Wer weiss, wie man die Performance entsprechend verbessern kann? Die
XML-Datei muss nur ausgelesen werden (also darin nichts suchen,
sortieren oder schreiben).

Umgebung: MS-Access97-SR2, Win2000-SP4 (jedoch auch Einsatz unter
WinXP, Vista)


Danke und Schöne Grüße
Kurt
 

Lesen sie die antworten

#1 Martin Honnen
03/03/2008 - 13:35 | Warnen spam
Kurt Langeder wrote:

In div. Foren habe ich gelesen, dass das mit dem DOM-Objekt
zusammenhàngt, da dieses nicht für große XML-Strukturen ausgelegt ist,
da hier der gesamte Tree im Speicher gehalten wird. Als Alternative
wird dann immer SAX genannt. Ich konnte aber bis keinen einzige
brauchbaren Code im Netz finden.



SAX kann man mit VBScript nicht benutzen, mit VBA (glaube ich) aber
schon. Die Doku dazu befindet sich in der MSXML SDK
<URL:http://msdn2.microsoft.com/en-us/library/ms762776(VS.85).aspx>.

Habe auch schon verschiedene MSXML-Versionen
("MSXML2.DOMDocument.3.0") und Parameter (z.B. xd.async = False,
xd.validateOnParse = False) probiert - hat aber alles nichts geholfen.

Die Datensàtze in der XML-Datei sehen etwa so aus:

<BEWEGUNG BewegungID="2007-11-12T07:26:50.641876" Kundennr="113899"
BuchDat="2007-10-01" BuchTxt="MUSTER JOHANN" BuchGrdlg="1000.00"
BuchSatz="20.00" BuchBetrag="200.00" WaehrungsCd="EUR"/>



Wenn die Strukur so einfach ist und bekannt ist, sollte man das einfach
per SAX parsen können.

Der VisualBasic-Code in Access:

Set xd = CreateObject("MSXML.DOMDocument")



MSXML.DOMDocument ist eine uralte Version von MSXML, man sollte
zumindest MSXML2.DOMDocument.3.0 verwenden. Mit VBA kann man doch auch
auf "late binding" verzichten und
Set xd As New MSXML2.DOMDocument30()
verwenden.

xd.Load myXMLDatei
Set docroot = xd.documentElement
With docroot.childNodes
For iCount0 = 0 To .length - 1
anzAtributtes0 = .Item(iCount0).Attributes.length
For jCount0 = 0 To anzAtributtes0 - 1
xNodeName0 = .Item(iCount0).Attributes(jCount0).nodeName
xTEXT0 = .Item(iCount0).Attributes(jCount0).Text
'--> Wert in Tabelle eintragen
Next
usw.


Wer weiss, wie man die Performance entsprechend verbessern kann?



Statt der beiden For-Schleifen kann man in VB-Dialekten doch For Each
verwenden, eventuell ist das schneller.
For Each child In docRoot.childNodes
For Each att in child.Attributes

Ansonsten würde ich zumindest das Element und das Attribut speichern
For iCount0 = 0 To .length - 1
Set child = .Item(iCount0)
anzAtributtes0 = child.Attributes.length
For jCount0 = 0 To anzAtributtes0 - 1
Set att = child.attributes.item(jCount0)
xNodeName0 = att.nodeName
xTEXT0 = att.text
'--> Wert in Tabelle eintragen
Next
sonst muss immer wieder .Item(iCount0).Attributes(jCount0) gesucht werden.


Martin Honnen MVP XML
http://JavaScript.FAQTs.com/

Ähnliche fragen