PDA

View Full Version : Verarbeitung der SQE



andreaspr@aon.at
15-12-09, 09:07
Hi,

ich hab ne Frage an die SQL/DB2-Profis:

Habe eine einfache Tabelle (5 Spalten) in ein Schema erstellt und diese beinhaltet knapp über 100 Datensätze.

Wenn ich ein folgendes Select absetze führt die SQE ein Table-Scan durch:

Select * from FTPLOG

Select * from FTPLOG where NR > 50

Wenn ich nun statt dem Größer (>) ein Gleich (=) verwende, erstellt mir die SQE einen Temporären Index und Row-Liste:

Select * from FTPLOG where NR = 50
Dies dauert um ein Vielfaches länger als die erste variante.

Ich habe beide Abfragen öfters ausgeführt, um der SQE die Möglichkeit zu geben den Zugriffspfad zu optimieren. Leider ohne Erfolg.

Ich hatte für diese Tabelle aus Testgründen einige Indizes erstellt. Diese sind jedoch nicht mehr vorhanden.

Weis jemand warum sich die SQE für solch einen Aufwand entscheidet, wenn ein einfacher Table-Scan um einiges schneller ist?

lg Andreas

Christian Bartels
15-12-09, 10:30
Ohne nähere Details zu kennen, ist es schwer zu sagen, warum der SQL-Optimizer eine bestimmte Entscheidung trifft. Bei diesem Beispiel wäre es hilfreich zu wissen, ob die Spalte NR eventuell einen (eindeutigen) Schlüssel darstellt, und wie sich die Werte innerhalb der Spalte NR verteilen. Außerdem könnte mit einfließen, über welches Interface das SQL-Statement abgesetzt wird (interaktives SQL, ODBC, embedded SQL), weil die Frage interessant sein kann, ob für "First I/O" oder für "All I/O" optimiert wird.

Grundsätzlich kann man wohl vermuten, daß bei einer Abfrage WHERE NR > 50 mehr Sätze zurückgegeben werden als bei einer Abfrage WHERE NR = 50, und das könnte die unterschiedliche Entscheidung des Optimizers erklären. Ein Table-Scan geht zwar bei einer relativ kleinen Tabelle schneller, kann aber bei wiederholtem Aufruf, wachsender Tabellengröße und kleiner Ergebnismenge negative Auswirkungen auf das Paging-Verhalten haben.

Mit freundlichen Grüßen,
Christian Bartels.

Fuerchau
15-12-09, 10:46
Da SQL ggf. ODP's ja offen hält, macht der Aufbau eines Index durchaus Sinn, damit alle folgenden Abfragen dann bei geöffnetem ODP erheblich schneller sind.
Im interaktiven SQL hast du natürlich Recht wenn du die Abfrage nur 1 Mal machst.
Aber woher soll der Optimizer das wissen ?
Wiederhole die Abfrage einfach mehrmals mit unterschiedlichen Schlüsseln und du wirst sehen, dass diese dann erheblich schneller sind.

andreaspr@aon.at
15-12-09, 10:57
Zunächst danke für die Antworten!

Die Tabelle ist wie folgt aufbeaut:

CREATE TABLE MYFTPLOG
(ACTCNT INTEGER
NOT NULL WITH DEFAULT,
BEZ CHAR (35)
NOT NULL WITH DEFAULT,
JOBNR INTEGER
NOT NULL WITH DEFAULT,
SEQNR INTEGER
NOT NULL WITH DEFAULT,
CMD CHAR (10)
NOT NULL WITH DEFAULT,
LOG VARCHAR (1024)
NOT NULL WITH DEFAULT,
DATUM TIMESTAMP
NOT NULL WITH DEFAULT)
Es gibt keine Primärschlüsseln (außer die RRN), da es keine Referenzierung auf andere Tabellen benötigt wird, bzw die Datensätze durchaus öfters auftreten können.
(ich weis, eine eigene Spalte mit laufenden Zähler und diesen als PK wäre schöner)

Den Test habe ich über den iSeries Navigator ausgeführt (JDBC).

Habe die Abfrage auch schon mit unterschiedlichen Filterungen durchgeführt. Das Ergebnis war immer das Gleiche. Table-Scan war immer schneller.
Das liegt mit ziemlich ganz sicher daran, dass es eben eine nur sehr kleine Tabelle ist.
Bin mir auch sicher, dass bei entsprechenden Datenmengen die Entscheidung der SQE die Richtige wäre.

Was ich interessant finde ist eben die Tatsache, dass für diesen Fall der Table-Scan schneller wäre, sich der Optimizer aber dennoch für einen anderen weg entschieden hat.

Beim ersten ausführen von WHERE NR = 50 hatte er auch einen Table-Scan durchgeführt (der war auch schneller).

B.Hauser
15-12-09, 13:27
Bei wenigen Sätzen/Zeilen und Spalten in einer Datei ist ein Table Scan immer schneller als ein Index-Zugriff!

Wenn die SQL-Abfrage wirklich mit der SQE und nicht mit der CQE ausgeführt wird, ist ein temporärer Index quasi permanent, d.h. existiert bis zum nächsten IPL und kann von allen Jobs (bzw. allen SQL-Abfragen) verwendet werden.

Der Optimizer interagiert mit dem Statistics-Mangager und erhält Informationen darüber wie groß der Anteil der ausgewählten Sätze am Gesamt ist. Bis zu ca. 20% wird ein Index bevorzugt.

Was mich allerdings wundert ist, dass bei einer Abfrage ein temporärer Index gebildet wird. Das passiert eigentlich nur, wenn man darauf besteht mit Echt-Daten (Datenkopie zulässig = *NO oder SENSITIVER CURSOR) zu arbeiten.

Birgitta

andreaspr@aon.at
15-12-09, 13:53
Hi Brigitta,
Danke für die Antwort!

Es ist alles reines SQL (Tabelle, Schema), und auch mit der SQE abgearbeitet. Der Temporäre Index bleibt auch bestehen.

Nach löschen, der Statistik-Daten hat der Optimizer zumindest keine Row-Liste erstellt.

Jetzt geht er nur noch über den Temporären Index.

Allerdings wenn ich den Filter entsprechend auswähle, dass möglichst wenig Datensätze ausgegeben werden, wird ein Table-Scan durchgeführt

Interessant ist auch, dass wenn ich den zusatz "FETCH FIRST ROW ONLY" verwende, trotzdem über den längeren Zugriffspfag gegangen wird, da trotzdem alle Datensätze gelesen werden und erst zum Schluss der erste Satz ausgegeben wird.

Danke jedenfalls für die Unterstützung!
lg Andreas

Fuerchau
15-12-09, 14:53
FETCH FIRST ROW ONLY ist für den Optimizer nicht relevant.
Hierfür ist OPTIMIZE FOR n ROWS gedacht.
Zusätzlichen Einfluss kann man über SET OPTION ALWBLK=..., ALWCPYDTA=... sowie die QAQQINI nehmen.

BenderD
15-12-09, 14:56
... da gehts der Query Engine nicht viel anders als der Kriminalpolizei: die rät - und manchmal falsch

D*B

andreaspr@aon.at
16-12-09, 07:29
Vielen Dank für die zahlreichen Antworten!!

Über SQL selbst hab ich es nicht mehr geschafft ein einfaches Table-Scan durchzuführen.

select * from myftplog
where actcnt = 1332
fetch first row only
optimize for 1 rows
for read onlyMüsste scheinbar wirklich wie Fuerchau geschrieben hat, mit SET OPTION oder in der QAQQINI einstellungen vornehmen, dass zB keine temporären Objekte erstellt werden dürfen. (Für diese Abfrage zumindest.)

So wie es aussieht ist die Antwort von BenderD am plausibelsten.

Danke auf jeden Fall für eure Hilfe :)