Anmelden

View Full Version : SQL Performance bei Aggregatfunktion



Seiten : [1] 2

dschroeder
07-03-13, 09:05
Guten Morgen,
wir müssen vor dem Schreiben von Datensätzen eine laufende Nr. für den neuen Datensatz vergeben. Es geht nicht um eine eindeutige laufende Nr. in der Datei, sondern um eine laufende Nr. pro "Auftrag". Das haben wir mit folgendem SQL umgesetzt:
select max(sp_sparaid) into :newNr
from idmspara where sp_se_rec = 107275170;

Die Datei ist natürlich nach sp_se_rec und sp_sparaid indiziert. Tabelle und Index sind mit SQL erstellt worden.

Wir haben festgestellt, dass das Ermitteln einer neuen Nr. ziemlich lange dauert. In einem Programm haben wir das Verfahren auf nativen RPG-Zugriff umgestellt (SETGT, READPE). Das geht dramatisch schneller (ca. Faktor 100).

Wenn wir Visual Explain richtig verstehen, generiert das SQL-Statement jedesmal eine temporäre Liste (manchmal mit allen Datensätzen der Tabelle). Ich vermute mal, dass SQL mit dem Erzeugen einer Kopie der Daten die Konsistenz der Daten sicherstellen will. Das wäre in unserem Fall aber nicht nötig. Ich weiß, dass keine Sätze (unter dem Schlüssel sp_se_rec) in die Datei geschrieben werden, solange das SQL-Statement läuft. Kann ich SQL irgenwie sagen, dass es auf das Kopieren der Daten verzichten soll?

Zur Klarstellung: Wenn ich eben von langer Ausführungszeit geschrieben haben, bewegen wir uns natürlich immer noch im Millisekundenbereich. Aber da extrem viele Sätze in sehr kurzer Zeit geschrieben werden, machen auch ein paar Millisekunden große zeitliche Probleme.

Gruß,
Dieter

Fuerchau
07-03-13, 09:43
Ggf. hilft hier ein absteigender Index:

Key1 asc, Key2 desc

select Key2 into :newNr
from idmspara where key1 = 107275170
order by key1 asc, key2 desc
fetch first 1 rows only;

BenderD
07-03-13, 09:57
... die Schnittmusterbögen von diesem "vielleicht explain" verwirren mehr, als sie erklären...
Temporäre Ergebnisdatei ist keine dirty Kopie (merkt man, wenn man das unter commit macht und am index only access), sondern wird in der Hoffnung gemacht, dadurch die Selektion zu beschleunigen.

Der absteigende Index hilft (bei mir zumindest) nix, das ist ihm Wurscht. Gute Ergebnisse erzielt man mit einer Keyverwaltungstabelle und einem universellen getKey, den man eventuell noch blocken lassen könnte, wenn mehrere Positionen aus einem Job geschrieben werden.

D*B

andreaspr@aon.at
07-03-13, 10:10
Ich kann mich nur der getKey-Methode anschließen.

Ansonsten kann es auch daran liegen, dass ...
*) ist die Reihenfolge vom Index falsch ist
*) der Index nicht verwendet werden kann, weil SQL intern Casten muss.
*) euer Release 6.1 oder kleiner ist, es ein Index ist mit Select/Omit und in der QAQQINI Ignore d. index gesetzt ist.
*) usw.

Wird denn überhaupt ein Index verwendet, wenn er alle Sätze liest?

lg Andreas

dschroeder
07-03-13, 10:29
Erstmal vielen Dank für die zahlreichen Antworten.
Hier noch ein paar Fakten dazu:

- Wir sind auf V7
- Der passende Index wird verwendet (laut Visual Explain)

Der Ablauf bei Visual Explain ist folgender:
1.) Index Probe
2.) Temporary List
3.) List Scan
4.) Final Select

Die Idee mit der Key-Tabelle passt mir für diese Aufgabenstellung im Moment nicht so gut. So eine Tabelle setzen wir im Moment immer da ein, wo wir globale IDs für Tabellen ermitteln (genauso, wie ihr das beschrieben habt: mit Sperrung).

Ich habe das betreffende Programm eben mal in einer Testumgebung so umgebaut, dass es nicht mit SQL arbeitet, sondern mit SETGT und READPE. Jetzt ist läuft das Programm in 30 Sekunden durch. Mit SQL dauert es 4 Minuten.

Meine eigentliche Frage ist, ob man davon ausgehen muss, dass SQL bei Aggregatfunktionen (insbesondere bei Max) viel langsamer ist als ein "manueller" Zugriff mit RPG-Bordmitteln. Wenn das so ist, muss man das eben hinnehmen und genau hinschauen, wann man welches Verfahren verwendet.

Dieter

BenderD
07-03-13, 10:49
... bei Aggregat Funktionen ist SQL im Allgemeinen schneller und im speziellen Fall langsamer und hier habt ihr es mit einem solchen zu tun.
DB2 auf der AS/400 ist immer noch optimiert für sequentiellen und ISAM (Index sequentiellem) Zugriffe. Das ändert sich nicht durch Marketing Aussagen (SQL ist immer schneller), egal wer das alles glaubt (soll es hier im Forum auch geben) und wird solange so bleiben, wie unter der Oberfläche eine ISAM Datenbank liegt.

D*B

dschroeder
07-03-13, 11:20
Vielen Dank für die Antwort.
Das bestätigt meine Vermutung. Wenn man das weiß, kann man sich beim Programmieren ja darauf einstellen.

Gruß,
Dieter

andreaspr@aon.at
07-03-13, 12:47
Lest ihr den neuen Key in der Anwendung an einer zentralen Stellen ein (Prozedur, Programm)?
Wenn du ein SELECT INTO machst erstellt das System automatisch einen Cursor dafür. Wenn du das SELECT INTO nun an verschiedenen stellen machst, hast du mehrere Cursor bei denen jedes mal der Datenpfad geöffnet werden muss.

In RPG macht man ja auch nicht ständig ein OPEN(Tabelle).

Starte einfach mal einen Performance Monitor.
Dort siehst du dann auch wie oft der Datenpfad geöffnet wurde und wie oft er wieder verwendet worden ist.
Im Idealfall muss er maximal 2 mal geöffnet werden.

dschroeder
07-03-13, 13:14
Wir haben ein Serviceprogramm, das den neuen Key ermittelt. Das ist die einzige Stelle, die das macht. Allerdings wird das Serviceprogramm von verschiedenen Programmen aufgerufen.

B.Hauser
07-03-13, 14:21
Wir haben ein Serviceprogramm, das den neuen Key ermittelt. Das ist die einzige Stelle, die das macht. Allerdings wird das Serviceprogramm von verschiedenen Programmen aufgerufen.

Wenn die Programme in unterschiedlichen Aktivierungsgruppen laufen und das Service-Programm mit Aktivierungsgruppe *CALLER erstellt wurde, kannst Du innerhalb eines Jobs mehrere Duplikate haben und folglich mehrere FULL OPENS, da jedes SQL-Statement seinen eigenen ODP erhält.

Birgitta