PDA

View Full Version : ODBC Performance Local vs. Remote



WeRi
13-02-12, 14:36
Hallo zusammen,

wir betreiben 2 iSeries, eine in einem LAN, die andere an einem entfernten Standort mit Anbindung via Citrix Access Gateway.

Beide Male verwenden wir den iSeries ODBC Driver mit identischen Einstellungen.

Während wir an der local betriebenen Maschine zufriedenstellende Laufzeiten haben, dauert speziell das Update von Datensätzen auf der Remote-Maschine ( obwohl leistungsfähiger ) mindestens 10mal so lang wie auf der Local-Maschine.

Hat jemand ein ähnliches Szenario und dieses Problem ebenfalls beobachtet bzw. vielleicht gelöst.

Danke für Anregungen und Hinweise.

BenderD
13-02-12, 14:52
... sinnigerweise fragt man da erst mal den Database Monitor (STRDBMON - zur Auswertung muss man sich dann mit Ooops Nerv rumquälen...), was da für Zeiten in der Datenbank verbracht werden.

D*B

Fuerchau
13-02-12, 15:17
Da nun mal remote noch das Netz dazwischen hängt, stellt sich die Frage, wo denn da der Zeitverlust ist.

Wie wird denn der Update durchgeführt ?
Gezielt mit einem Update-SQL oder durch ADO-Automatismen o.ä. ?
Der genaue SQL für den Update wäre da schon hilfreich.

Ggf. werden hier einfach zu viele Daten über die Leitung gejagt und hier ist der Engpass zu vermuten.

Ich hatte da auch schon so diverse Zeitprobleme, da hier die Up-/Download-Geschwindigkeiten über das Internet ja doch sehr unterschiedlich sind.
Was nützt mir da ein Download von 32MBit wenn der Upload nur 1MBit oder weniger beträgt.

Manchmal hilft es auch, in der ODBC-Konfiguration die Komprimierung ein- oder auszuschalten, je nach dem, ob im VPN die Komprimierung unterstützt wird oder nicht.

WeRi
13-02-12, 16:37
Das angesprochene Datensatz-Update erfolgt durch ein PC-Programm via ADO-RecordSet, ganz klassisch:

- Datensatz einlesen
- Datenbankfeldwerte ändern
- Datensatz ändern

Das Ganze stellt sich im Programmcode verkürzt so dar:

select * from MyFile für update

Z-ADD NewValue ODBC.RecordSet("MyField")

ODBC.RecordSet.Update()

Fuerchau
13-02-12, 17:26
Dann ist genau das der Engpass.
Dieser Defaultupdate generiert einen relativ langen SQL der ja auch konkurierende Updates abfangen soll.
Je nach dem, wie viele Felder da vorhanden sind kann das ganz schön dauern.
Der SQL sieht in etwa so aus:

update myfile
set f1=?, f2=?, f3=? ...
where f1=? and F2=? and f3=? and ...

D.h., in der Set-Klausel werden alle Felder mit dem neuen Wert gesetzt, in der Where-Klausel werden alle Felder mit dem Ursprungswert gesetzt, so dass tatsächlich nur ein Update erfolgt, wenn der Satz noch nicht durch einen anderen Prozess verändert wurde.
Je nach dem, wie viele Sätze so geändert werden, wird eben für jeden Satz so ein Update durchgeführt.
Über die Filter-Eigneschaft kann man dann feststellen, welche Updates nicht erfolgreich waren.

Im LAN geht das ja noch, aber per WAN gibts halt die Zeitprobleme.

Beschleunigen kannst du das nur, wenn du den Select auf genau die Felder beschränkst, die du für die Anwendung benötigst.

WeRi
15-02-12, 07:55
Vielen Dank an Euch,

die Problematik ist noch nicht gelöst, aber die Tips haben mich bei der Auswertung des Datenbank-Monitors schon mal weitergebracht.

Vorab schon mal ein Tip:

Bisher habe ich das SQL-Statement per RecSet.Open(MySQLStmt) abgesetzt und anschliessend mit RecSet.MoveFirst() auf den Datensatz positioniert.

Dieser MoveFirst ist nicht erforderlich und sollte weggelassen werden. Ohne diesen erhöht sich der Durchsatz ( zumindest remote ) um fast 50%.

Fuerchau
15-02-12, 09:09
Die Performance lässt sich ggf. durch ClientCursor noch steigern.

Empfehlenswert ist auch der Einsatz eines CommandObjekts mit ParameterMarkern, wobei CA die Anzahl und den Typ der Parameter auch noch selber lädt.

with MyCommand
.CommandText="Select ... where Key=?"
set .ActiveConnection=MyConnection
end with

MyCommand(0) = "Key"
with MyRecordset
if .State=adStateClosed then
MyRecordset.Open MyCommand
else
MyRecordset.Requery
endif
end with

Zusätzlich kann man in der ODBC-Konfig auch noch das Flag "Daten vorab laden" setzen, man spart dadurch zusätzliche Netzrequests.

Beim Einsatz von ClientCursor lassen sich auch mehrere Veränderungen in einem Recordset durchführen (Update/Addnew/Delete), die dann mit einem Request "UpdateBatch" nach oben geladen werden.
Durch .Filter=adFilterError (oder ähnlich) lassen sich dann fehlerhafte Updates gezielt behandeln.

WeRi
11-04-12, 12:10
Hallo zusammen,

die Performance-Unterschiede in LAN und WAN treten nicht nur beim Update, sondern auch im ReadOnly-Modus auf.

Der Einzelsatz-Zugriff ( vergleichbar dem RPG-CHAIN ) ist im WAN-Betrieb extrem langsam.

Hier sinngemäss der Programm-Code:

SQL = 'select * from DATEI where ...'

RecordSet.Open (SQL)

Mir scheint, dass das Öffnen des RecordSets der Flaschenhals ist.

Gibt's dafür eine Erklärung ? Danke

Fuerchau
11-04-12, 14:48
Die Frage ist, wieviele Daten denn da so übertragen werden.
Man bedenke, dass der Open je mehrere Netzrequests auslöst.

In der ODBC-Konfig kann man aktivieren(ich glaube Register Server), "SQL Vorablesezugriff", dies reduziert die Requests etwas.

Um genaues zu analysieren, kann man über den ODBC-Manager einen SQL-Trace ziehen, der allerdings extrem verlangsamt.
Hier sieht man dann genau, was da so alles abgeht.

Zusätzlich ist es natürlich immer ein Unterschied, ob man einen SQL zusammenbaut oder mittels Command-Objekt und Parametern arbeitet.

Hier kann man dann auch so verfahren:

dim MyCmd as new ADODB.Command
MyCmd.CommandText = "select * from myfile where key=?"
set MyCmd.ActiveConnection=MyConnection

dim MyRcd as new ADODB.Recordset

MyCmd(0) = "Key"
if MyRcd.State = adStateClosed then
MyRcd.Open MyCmd
else
MyRcd.Requery
endif

Das dauert dann nicht mehr ganz so lange.