PDA

View Full Version : Und wieder mal SQL-Optimizer



Seiten : [1] 2

Fuerchau
22-06-17, 15:15
Wer hat die IBM-Entwickler eigentlich auf den Trichter gebracht, Funtionen des Selects vor der Where-Klausel zu berechnen?
Beispiel:

select
date(digits(ltlpdn) concat '000000') ltdndate
from lpmt a
where ltlpdn > 20140000

Der SQL stirbt mit ungültigem Datum, wenn das Feld LPLPDN = 0 ist, obwohl ich das ja per Where-Klausel ausgeschlossen habe.

Insgesamt ist der SQL etwas komplexer und SQL kann sich für keinen Index entscheiden (trotz aller Vorschläge des Optimizers) und führt einen Table-Scan durch.

Ich habe die Whereklausel schon erweitert, aber das macht keinen Unterschied, die Datumskonvertierung erfolgt vor der Where-Prüfung.

Soviel zum Thema: denn sie wissen, was sie tun...

dschroeder
22-06-17, 16:12
Das finde ich auch merkwürdig. Sind deine Daten vielleicht trotz deiner where Klausel ungültig? Wenn der Optimizer das wirklich so seltsam macht, bleibt dir vielleicht nur dir Möglichkeit, das irgendwie mit einer case-Anweisung zu lösen.
Aber ich würde auch erwarten, dass die select Auswertung erst nach dem where ausgeführt wird.

Fuerchau
22-06-17, 16:22
Die Datumskonvertierung wird ausschließlich in der Select-Liste durchgeführt.
In der Whereklausel erfolgt da kein Zugriff.
Wenn ich den SQL vereinfache und nur auf das Where ltlpdn > 20140000 prüfe, wird ein Index verwendet und die fehlerhaften Daten werden überlesen.
Sobald der volle SQL genommen wird, schmeißt der SQL einen Cast-Fehler auf das DATE... ins Joblog ohne Angabe einer Satznummer (Satznummer 0).

dschroeder
22-06-17, 16:39
Ist deine Logik wirklich richtig? Warum werden denn an ltlpdn noch 6 Nullen drangekettet? Aus 6 Nullen wird doch nie ein vernünftiges Datum, oder?

BenderD
22-06-17, 16:40
... es gibt halt keine Garantie auf eine bestimmte Reihenfolge der Auswertung von Klauseln zur Laufzeit (und das ist auch gut so!!!). Wenn man solche Huddeltadümmer hat, dann braucht man halt eine intelligentere Konvertierungsfunktion, die das rausmaskiert, oder man macht es richtig und saniert das im Datenbankdesign.

D*B

dschroeder
22-06-17, 16:49
Hm, ich bin mir mit der Logik noch nicht sicher. Wenn ich das richtig verstehe, erzeugt digits doch einen String, der aus Ziffern besteht. Und mit "date" willst du das in ein echtes Datum umwandeln. Dann muss der String doch eine gültige Datumsrepräsentation ergeben (z.B. '2014-05-26' oder so).

Da ist der Zusammenbau doch etwas komplizierter, als einfach 6 Nullen dranzuhängen. Vielleicht mach ich aber auch gerade einen Denkfehler ...

Fuerchau
22-06-17, 17:00
Nun, damit hast du bedingt recht. Es ist auch ein RPG-Timestamp (Anweisung Time) "JJJJMMTTHHMMSS" erlaubt.
Probiers aus...
Übrigens geht auch (ja nach PTF)
"DATE(CHAR(MyDate * 1000000))".
PTF ist deshalb wichtig, da SQL u.U. eine Integer-Multiplikation draus macht obwohl 14 Stellen nachweislich größer als 10 Stellen sind (davon nur 9 signifikante).

@D*B
haha...
Sag das mal den Kunden... mit ihrer Altanwendung.
Eine Whereklausel ist ein Filter auf die Daten, der früher (bis V6R1) immer vorab geprüft wurde.
Der Unterschied hier ist sogar noch so, dass eine UDF in der Select-Liste nicht aufgerufen wird, sondern erst auf den gefilterten Daten. Macht ja auch keinen Sinn, erst mal was zu berechnen was ich dann wieder wegschmeiße.

BenderD
22-06-17, 17:54
@D*B
haha...
Sag das mal den Kunden... mit ihrer Altanwendung.
Eine Whereklausel ist ein Filter auf die Daten, der früher (bis V6R1) immer vorab geprüft wurde.
Der Unterschied hier ist sogar noch so, dass eine UDF in der Select-Liste nicht aufgerufen wird, sondern erst auf den gefilterten Daten. Macht ja auch keinen Sinn, erst mal was zu berechnen was ich dann wieder wegschmeiße.

... das mit den Altanwendungen, die Frage ist halt, ob man das im Viewlayer (DDS erstellt!!!) rausmaskieren kann, ich denke da an ein zusätzliches Feld, das man für die Altanwendung weglässt und per Trigger mitpflegt.
Was ich noch nicht ganz verstehe, wo knallt das wirklich? Das Feld LPLPDN finde ich im SQL Statement nicht.

Dieter

kitvb1
23-06-17, 06:42
...
select
date(digits(ltlpdn) concat '000000') ltdndate
from lpmt a
where ltlpdn > 20140000

Der SQL stirbt mit ungültigem Datum, wenn das Feld LPLPDN = 0 ist, obwohl ich das ja per Where-Klausel ausgeschlossen habe.


Tipp fehler??



(...und brauche wenigstens 20 Buchstaben/Antwort :) )

Fuerchau
23-06-17, 07:31
Jo, Tippfehler sind doch wohl mal zulässig. Es heißt natürlich LTLPDN.