PDA

View Full Version : SQL Schlüssel herausfinden



Seiten : [1] 2

Rincewind
30-01-04, 11:13
Hallo zusammen,

Ich habe ein neues SQL Geschrieben welches leider immer wieder einen Index über eine der Auswahldateien aufbaut.

Die Physische Datei ist eindeutig geschlüsselt und ich setze den INNER JOIN auf über dieses Schlüsselfeld.

Die Felder die ich auswähle sind allerdings in keinem Schlüssel vorhanden.

Als normale Vorgehensweise setze ich immer bei den ersten Läufen ein STRDBG davor um die genaueren SQL informationen zu erlangen.

Nun sagt er mir aber leider nicht einen Schlüssel zur Optimierung (wie er es sonst so gerne macht) sondern gibt mir nur ein
*MAP ASCEND
als Schlüsselwort für die temporäre Datei an.


Die Frage nun:
Kann ich irgendwie dieses *MAP (welches wohl ein zusammengesetztes Feld ist) auflösen sodass ich den optimalen Zugriffsschlüssel herausfinden kann?

Release ist übrigens 520
Das SQL ist ein SQL mit UNION
Die Felder aus der grossen Datei (über die der Index erstellt wird) sind im GROUP BY aber nicht im Order by.


Habe das ganze nun mit einem kleinen VorSQl und einer CHAIN Operation gelöst, es wäre nur schön zu wissen wie man an diese Information kommt.

Dank euch schonmal im voraus
und TGIF

Rince

Fuerchau
30-01-04, 11:20
Unter V5R2 sollten doch keine temp. Indizees mehr aufgebaut werden (mal so dahinstelle).

Wie sehen die Schlüssel der Join-Datei aus ?

Sind ggf. die Feldformate in der Join-Bestimmung nicht passend ?

Ausserdem berücksichtigt SQL ALLE vorhandenen LF's einer PF !

Poste doch mal deinen SQL.

Rincewind
02-02-04, 10:00
Die Schlüssel der Join Dateien sind gleich definiert.
Die Kleinste Datei steht auch vorne (KRT001 und KRTHST sind gleich aufgebaut, das eine sind die aktuellen das andere die historischen Daten)
Die Zuordnung KKHBCH und TRFBCH sind jeweils eindeutig, beide Felder sind gleich (8 A) definiert.

Das SQL alle berücksichtigt war mir auch klar, was ich meinte war:
Er verwendet den Zugriffspfad nicht im SQL (will heissen er baut sich einen neuen auf)


Rince
anbei das SQL, (wenns hilft)

SELECT
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT,
DECIMAL(SUM(C.KRTREC), 7, 0)
FROM KRTKOMH A INNER JOIN TRFHDR B ON A.KKHBCH = B.TRFBCH
INNER JOIN KRT001 C ON A.KKHPAL = C.KRTKPL
WHERE
C.KRTSTY = :STYLE
AND C.KRTCOL = :COLOUR
AND C.KRTSIZ = :SIZE
GROUP BY
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT
UNION
SELECT
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT,
DECIMAL(SUM(C.KRTREC), 7, 0)
FROM KRTKOMH A INNER JOIN TRFHDR B ON A.KKHBCH = B.TRFBCH
INNER JOIN KRTHST C ON A.KKHPAL = C.KRTKPL
WHERE
C.KRTSTY = :STYLE
AND C.KRTCOL = :COLOUR
AND C.KRTSIZ = :SIZE
GROUP BY
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT
ORDER BY KKHPAL DESC, KKHVCN

BenderD
02-02-04, 11:24
Halo Rince,

eher eine (nicht vage) Vermutung, das dürfte der union sein, der das versaut, hast Du mal beide Teile separat versucht???
Sollte es das sein, der union sieht mir unecht aus (die ausgewählten Felder sind identisch),das müsste auch ohne gehen (irgendeine Kopplung mit or in der where Bedingung) letzteres könnte allerdings auch ein Where In zur Folge haben und das könnte dann wieder alles versauen.
Probier doch erst mal beide Teile einzeln aus, ob da ein Index passend gefunden wird.

Dieter Bender

Fuerchau
02-02-04, 12:28
Das Problem dürfte hier die "Group by"-Klausel sein:

Das Grouping erfolgt auch am schnellsten, wenn ein Schlüssel für die Felder vorhanden ist.
Desweiteren werden die Group-Felder aus der Join-Datei und nicht aus der Primär-Datei aufgebaut.

Da bei einem INNER-Join nicht die Größe der Tabelle sondern nur die EINDEUTIGE Beziehung eine Rolle spielt, drehe die Beziehung der Dateien "KRTKOMH A INNER JOIN TRFHDR B" einfach um, so dass das Grouping über die Primär-Datei läuft.

Prüfe, ob für deine Group-Felder Indizees (LF's) vorhanden sind.

@Dieter

Der UNION ist erforderlich, da in der 2. Joinbeziehung verschiedene Tabellen angegeben sind.

Rincewind
02-02-04, 12:47
Hy ihr,

@Dieter,
Wie Fürchau schon sagte, ich habe da 2 verschiedene Dateien (die den gleichen Aufbau haben)


@Fürchau

Für den Group by wollte ich ja einen Index erstellen (über die TRFHDR)
aber nach welchem Schlüssel wäre denn der beste Zugriff?

Die vorhandenen Schlüssel beinhalten nur TRFBCH
Die Datumsfelder sind nicht enthalten.

Rince

B.Hauser
02-02-04, 13:33
Hallo Rince

Du erstellst einen Index über die Felder aus der Datei TRFHDR, die im Groupy by angegeben sind.

Ebenso würde ich einen Index für die anderen Dateien erstellen, aus denen du Felder im Group by angegeben hast.

Birgitta

Fuerchau
02-02-04, 13:53
Da die WHERE-Klauses ausschließlich Felder aus Datei C selektiert, würde ich diese als Primary angeben.

Auf die Grouping-Felder sollte ein Index liegen.
Das Problem hierbei ist, dass sowohl aus der 1. als auch der 2. Tabelle Gruppenfelder verwendet werden.

Hierbei hilft eigentlich nur ein WITH-Konstrukt, in dem die einzelnen Select's nur temporäre Zwischen-Ergebnisse liefern und erst zum Schluss das Grouping auf die Ergebnistabelle anwenden.
Beispiel:



with
xERG1 as (select ... from ... where ...
[union select ... from ... where ...]
)
,xERG2 as (select ... from xERG1 inner join ... on ...)
,xERG3 as (select ... from xERG2 inner join ... on ...)

select ... from xERG3
group by ...
order by ...


Je nach Optimierungsart kann das zu besseren Ergebnissen führen, da ein Index nur auf den Teilergebnissen angelegt wird und wenn diese gering genug sind fällt das kaum noch auf.

BenderD
02-02-04, 14:01
Hallo Rince

@Baldur
@Rince

wenn meine Brille was taugt, dann ist der Union unecht, was haltet
ihr von:
SELECT
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT,
DECIMAL(SUM(C.KRTREC), 7, 0)
FROM KRTKOMH A INNER JOIN TRFHDR B ON A.KKHBCH = B.TRFBCH
where A.KKHPAL IN
(
select C.KRTKPL
from KRT001 C
where
C.KRTSTY = :STYLE
AND C.KRTCOL = :COLOUR
AND C.KRTSIZ = :SIZE
)
or
A.KKHPAL IN
(
select D.KRTKPL
from KRTHST D
where
C.KRTSTY = :STYLE
AND C.KRTCOL = :COLOUR
AND C.KRTSIZ = :SIZE
)
GROUP BY
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT
soweit die erste Idee.

Union führt in Verbindung mit einigem zu full Tablescans, die dann logischerweise für den Group by einen temporären Index zur Folge haben. Meine Bedenken gehen allerdings in die Richtung, dass der WHERE IN auch nicht zu den Highlights von DB2/400 gehören.
Wenn das ganze signifikant für irgendwas ist, dann könnte man eventuell noch einen Filter als SQL UDF für die Bedingung auf C und D schreiben und für diesen Multithreading erlauben.

Dieter Bende

Fuerchau
02-02-04, 18:45
@Dieter

Da die Summe über ein Feld in Datei C gebildet werden soll, geht das so leider nicht :D

Meine Lösung:



with
krt (krtkpl, krtrec)
as (select krtkpl, krtrec from krt001
where KRTSTY = :STYLE
AND KRTCOL = :COLOUR
AND KRTSIZ = :SIZE
union
select krtkpl, krtrec from krthst
where KRTSTY = :STYLE
AND KRTCOL = :COLOUR
AND KRTSIZ = :SIZE
)

, krtkom as (select kkhvcn, kkhpal, kkhsts, kkhbch
from krtkomh
where kkhpal in (select krtkpl from krt)
)

SELECT
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT, DECIMAL(SUM(C.KRTREC), 7, 0)

FROM KRT C
, krtkom A
, TRFHDR B

where C.KRTKPL = A.KKHPAL
and A.KKHBCH = B.TRFBCH

GROUP BY
B.TRFSCN, B.TRFSDT, A.KKHVCN, A.KKHPAL, A.KKHSTS,
B.TRFRCN, B.TRFRDT