Optimierung Schnittstelle – Teil II

Wie schon unter Optimierung Schnittstelle berichtet, konnte der Datenabruf über eine Schnittstelle von etwa 40min auf 3min Verarbeitungsdauer reduziert werden. Die Ursache für die lange Verarbeitungsdauer war die Nutzung einer String-Variable anstelle des StringBuilders in VB.net.

Allerdings waren wir auch der Ansicht, dass da noch viel Zeit verloren geht bei mehr als 260.000 Einzel-Inserts in die Datenbank. Also haben wir uns noch einmal ein halbe Stunde mit der Thematik beschäftigt und eine DataTable erstellt, die die Felder dynamisch ermittelt und die richtigen Datentypen setzt.

Diese wird dann zunächst mit den Daten aus dem Webservice befüllt und dann in 10.000er Blöcken per BulkInsert in die Zieldatenbank übertragen.

Der Effekt war dieser Modifikation besser als erhofft:
Anstelle der 3min geht die Verarbeitung damit nun in etwa 20s. Eine ordentliche Steigerung, wenn man sich die ursprünglichen 40min Verarbeitungszeit vor Augen führt.

So machen Optimierungen Spass!

Optimierung Schnittstelle

Kürzlich kam ein Kunde auf uns zu, dem das Laufzeitzeitverhalten für eine Schnitsttelle nicht gefiel:

Ausgangsituation

Über einen Webservice werden täglich in einem Teilschritt rund 270.000 Datensäze abgerufen. Diese müssen zum Teil umformatiert werden und das Ergebnis (die Anzahl der Zeilen bleibt dabei unverändert) in eine Datenbanktabelle (MSSQL) eingefügt werden.

Erster Modifikationsversuch

Zunächst lag Nahe, dass das Schreiben mit Einzel-Inserts zu den langen Laufzeiten führt. Also wurde VB.net-Code derart modifiziert, dass immer 10.000 Zeilen zunächst in eine lokale DataTable im Arbeitsspeicher geschrieben wurden und diese dann per Bulk-Insert in die Zieltabelle eingefügt wurden.

Die Verarbeitung war zunächst “gefühlt” schneller, wurde dann aber zusehends langsamer. Also musste noch ein weiterer Grund für den Performanceeinbruch vorliegen.

Die Lösung

Zur Verarbeitung der Daten wurde der XML-Node als String verarbeitet. Dabei mussten Bestandteile der Daten per replace für die Aufbereitung der Zieldatenbank geändert bzw. neu formatiert werden.

Die Lösung bestand darin die Verarbeitung von Strings zu verhindern und die Daten, soweit es geht im StringBuilder zu verarbeiten. Erst am Ende ist eine Konvertierung zu einem String notwendig, um die Daten per split() in ein Array zu übernehmen.

Außerdem wurde die For…Next-Schleife derart modifziert, dass nicht erst der jeweilige XML-Node gesucht werden muss. Mit For..Each werden einfach der Reihe nach alle Knoten durchlaufen.

Im Gegensatz zum BulkInsert, gab es nun keinen Geschwindigkeitsverlust mehr. Die Verarbeitungszeit konnte damit von ursprünglich mehr als 40min auf etwa 4min gesenkt werden – und das noch ohne BulkInsert. Den Einfluss von BulkInsert testen wir aber auch noch in den kommenden Tagen.

' Vorher:
For i = 0 To colmax - 1

	result = XmlDecodeData(xmldoc.GetElementsByTagName("data:Result").Item(i).InnerXml.ToString)

	' Umstellung Trennzeichen damit Semikolons in Textfeldern nicht stören
	result = Replace(result, """;""", """||""")
	cols = Split(result, "||")
	
	' ...weiterer Code
	
Next

Im ursprünglichen Code, gab es durch die String-Variablen gleich mehrere Stellen, die in StringBuilder-Funktionen konvertiert werden mussten. Die XmlDecodeData wurde ebenfalls in eine StringBuilder-fähige Version umgebaut:

' Nachher:
Dim result As StringBuilder = New Stringuilder("")
Dim cols() As String

For Each XmlRow In xmldoc.GetElementsByTagName("data:Result")

	result.Clear()
	result.Append(XmlRow.InnerXml.Replace(""";""", """||""") 
	result = XmlDecodeDataSB(result)
    cols = Split(result.ToString(), "||")
	
	'... weiterer Code
Next

Weitere Vorschläge Willkommen! Update folgt..

Diese Seite verwendet Cookies, um die Nutzerfreundlichkeit zu verbessern. Mit der weiteren Verwendung stimmen Sie dem zu.

Datenschutzerklärung