Anmelden

View Full Version : Kann ein SQL Cursor übertragen werden?



Seiten : 1 [2] 3

dholtmann
10-03-16, 15:25
Hallo,
habe jetzt alles hinbekommen.
Meine Prozedur zum Lesen sieht wie folgt aus:


dcl-pi pr_ar_readsql ind;
DS_Input likeds(DS_Datei);
end-pi;
//-----------------------------------------------------------------------
// Variablen
//-----------------------------------------------------------------------
dcl-ds DS_SQL_Out ext extname('AR') end-ds;
dcl-s ind_fehler ind;
dcl-s cha_statement char(500);
//-----------------------------------------------------------------------
// Verarbeitung
//-----------------------------------------------------------------------
ind_fehler = *off;
exec sql fetch cursor_ar into :DS_SQL_Out;
if sqlcode <> 0;
ind_fehler = *on;
if sqlcode = 100;
exec sql close cursor_ar;
clear ds_input;
endif;
else;
DS_Input = DS_SQL_Out;
endif;


Bei ungefähr 600.000 Sätzen benötige ich ungefähr 38 Sekunden.
Native IO schafft das Ganze in 3-7 Sekunden.
Liegt das am Prozeduraufruf? Oder am Fetch?
Habt ihr Ideen wie das schneller funktioniert?

Fuerchau
10-03-16, 15:48
Da kommt schon einiges an Overhead zusammen.
Zunächst mal die Frage ob du bei Native-IO die Datei als Input oder Update definiert hast?
Beim Input wird geblockt gelesen und dann z.T. nur noch Zeiger versetzt.
Realer Vergleich geht nur mit ungeblocktem Lesen.
Hast du für Native-IO auch den Prozedur-Overhead programmiert?

Und dann schau dir mal die Listauflösung an.
Für SQL wird jede Variable 2 mal deklariert, 1 x SQL-XXX und dann eben Dein Feld.
Der Overhead liegt nun in den vielen Aufrufen und Übergaben und zusätzlichen Moves begründet.

dholtmann
10-03-16, 16:22
Stimmt, der Aufruf klaut Einiges.
Wenn ich innerhalb der Prozedur alle Sätze fetche sind es noch 11Sekunden.

Die Grundidee war jedoch das read auf die Logische auszulagern, um alle Dateizugriffe zentral nur noch über ein Prozedur statt aus Programmen zu steuern.
Wenn es in Summe so viel Zeit kostet kann ich das bloß leider nicht nutzen.

BenderD
10-03-16, 16:26
... gute 15.00 pro sec. sind doch ein guter Wert, was hast Du denn wirklich vor?

D*B


Hallo,
habe jetzt alles hinbekommen.
Meine Prozedur zum Lesen sieht wie folgt aus:


Bei ungefähr 600.000 Sätzen benötige ich ungefähr 38 Sekunden.
Native IO schafft das Ganze in 3-7 Sekunden.
Liegt das am Prozeduraufruf? Oder am Fetch?
Habt ihr Ideen wie das schneller funktioniert?

dholtmann
10-03-16, 16:42
Nunja bisher laufen sämtliche Programme auf Logischen.
Egal, ob 1 Satz gelesen wird oder 25 Millionen.
Für zukünftige Programme wollte ich das halt generell auf diese Art auslagern.
Wenn ein Programm jetzt im Extremfall schon 2 Stunden läuft, habe ich einfach die
Befürchtung, dass es durch das vielfach langsame Lesen in Summe zu erheblichen Verzögerungen kommt.

BenderD
10-03-16, 16:56
... wenn ein Programm jetzt 2h läuft, dann kann das nicht an den reads liegen, das müssten nach Deinen vorherigen Angaben dann ja 1 Milliarde reads sein. Bei SQL und read only, kann so ein Programm auch block weise fetchen, da dauern 1000 Sätze lesen ähnlich lang wie ein einzelner fetch. Im übrigen reduziert der sinnvolle Einsatz von SQL die Anzahl der reads auf einen Bruchteil im Vergleich zu rekord Löffel.

D*B

Fuerchau
10-03-16, 17:26
Da kann ich Dieter nur zustimmen.
Wenn die für die Verarbeitung von 600.000 Sätzen 2 Stunden brauchst, sind 38 Sekunden zu vernachlässigen.
Das Ganze auf Basis von LF's aufzubauen ist sowieso Humbug da du für jede kleine Sortierung eine LF brauchst. Und dazu noch der Overhead für das ermitteln der Schlüsselfelder.
SQL in Prozeduren/Funktionen zu packen sollte generell eher auf Funktionen beschränkt werden und nicht die alten Filehandler ersetzen.
Der Nachteil ist eben durch die Übergabe von Strukturen wieder die Komplettwandlung aller Beteiligten.
Bei SQL kannst du den Vorteil, nur die Informationn zu lesen, die gerade benötigt werden, auf diesem Wege gar nicht nutzen.
Und was machst du mit Joins?
Kommen die bei dem Konzept nicht vor?
Ich mache z.B. einen Select auf Bewegungsdaten und hole mir per Join gleich die benötigten Stammdatenfelder dazu. Nach deiner Methode wäre das nicht zulässig.
Der Programmieraufwand wird dadurch nicht unerheblich größer.

Also Fazit:
Ich halte deinen Ansatz eher für eine Fingerübung.

dholtmann
11-03-16, 07:42
Hm klar, mit den Logischen ist das keine Ideallösung,
aber ich hatte angedacht das optional zu regeln, so dass Leute die sich mit Views noch nicht wohl fühlen weiter diese benutzen können und Andere auf Views zugreifen.

Zum Punkt bezüglich des Wandelns,
Ich habe überlegt die eigentliche Fetchroutine in eine Copystrecke auszulagern, die dann ins Aufrufprogramm eingebunden wird.
Bekomm ich da Probleme? Hatte gehofft, dass neue Felder dann nur bis zum Wandeln nicht mit gefetcht werden, da halt die DS zu klein ist.
Lieg ich da falsch?

Wie weit das später wirklich Einsatz findet weiß ich auch noch nicht.
Momentan ist das für mich selbst mehr Forschung, da ich noch nicht lang mit Prozeduren und überhaupt embedded sql arbeite.

BenderD
11-03-16, 08:02
... viel zu kompliziert gedacht!
- eine View ändert man niemals nicht!!!
- auf Tables greift man niemals nicht zu!!!
- wenn Felder dazu kommen, gibt es eine weitere View, wer die Felder braucht, nimmt die, wer nicht, eben nicht
- solange ich die vorhandenen Views darstellen kann, kann ich am Aufbau der Datenbank ändern (normalisieren!!!), ohne dass die Anwendungen was merken.
- hierbei können instead Trigger selbst joins updaten

D*B

PS: das mit den Copystrecken ist ein Rückschritt, was das kann, können subprocedures besser!!!

Fuerchau
11-03-16, 09:55
Neben dem Problem, einen Cursor zurückzugeben.
Wenn das Programm nicht neu gewandelt wird, stirbt der Fetch da zu viele (oder zu wenige) Felder verfügbar sind. Der Fetch ist da statisch.

Vergiss den Ansatz SQL's in Prozeduren auszulagern.
Denke lieber darüber nach, "Geschäftslogik" in Prozeduren/Funktionen zu packen.
Du gewinnst nichts, wenn du die Aufrufe von SQL's wie die alten RLA-Zugriffe erzwingst.
Im Gegenteil, du verlierst nur (s.o. Performance)!