Oracle 8.1.6 und performance

folgendes statement:

select a, b, c, d, … from tabelle
where a = (select min(a) from tabelle where a between [wert] and [wert])

dauert bei mehreren millionen eintraegen doch recht lange.
der datentyp von a ist number.
auf a liegt auch ein index.
gibt es vielleicht noch andere (und wenn ja welche) moeglichkeiten diese statement ein wenig zu beschleunigen??

der jan

Hallo Jan,

ich helfe dir gerne, setzte aber vorraus, dass du uns über das Ergebnis informierst.

Ich denke du willst den kleinsten Wert einer Range suchen. Hiermit geht es auch (und ich denke es geht schneller):

SELECT a,b,c,d
FROM (SELECT a,b,c,d
FROM tabelle
WHERE a BETWEEN [wert] AND [wert]
ORDER BY a ASC)
WHERE ROWNUM = 1
/

Am Beispiel der Tabelle emp - Wer hat den kleinsten Verdienst zwischen 500 und 3000 :

SELECT *
FROM (SELECT *
FROM emp
WHERE sal BETWEEN 500 AND 3000
ORDER BY sal ASC)
WHERE ROWNUM = 1
/

Ich gehe dabei davon aus, dass mein Statement umso schneller läuft, je weniger Zeilen im spezifizierten Wertebereich liegen:

Gruß Janus

PS: Bitte nicht das Feedback vergessen.

mit rownum haben wir auch schon rumexperimentiert. leider habe ich die bedeutung dieses ein wenig falsch interpretiert. es funktioniert >> schneller.

wunderbar!!

zu bemerken ist bei diesem rownum leider ein kleiner nachteil:
man kann nur [Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Dumme Frage zum Tage, hat es einen bestimmten Grund warum du statt:

SELECT a,b,c,d
 FROM tabelle
 WHERE 
 ( a BETWEEN [wert] AND [wert] )
 AND ( ROWNUM = 1 )
 ORDER BY a ASC)
 WHERE ROWNUM = 1
/

Die Variante über zwei SELECTs wählst?

Grüße, Robert

Dumme Frage zum Tage, hat es einen bestimmten Grund warum du
statt:

SELECT a,b,c,d
FROM tabelle
WHERE
( a BETWEEN [wert] AND [wert] )
AND ( ROWNUM = 1 )
ORDER BY a ASC)
WHERE ROWNUM = 1
/

Die Variante über zwei SELECTs wählst?

Es gibt nur einen Grund - ich will das richtige Ergebnis.

Die Rownum wird direkt nach der FROM-Klausel vergeben. Wenn der kleinste Wert zufälliger Weise die kleinste Rownum hat, muss das aber nicht immer so sein. Mein Tipp - Testhalber mal den Index umgehen (… WHERE a+0 BETWEEN [wert] AND [wert] …) .

Anschließend den gesuchten Wert löschen und gleich wieder einfügen. Wenn du dein Statement jetzt noch einmal laufen läßt, könnte ein falsches Ergebnis rauskommen.

Gruß der Janus

PS: Abgesehen davon ist die Klammer nach der ORDER BY-Klausel und die zweite WHERE-Klausel falsch. Das Statement sollte so nicht laufen …

zu bemerken ist bei diesem rownum leider ein kleiner nachteil:
man kann nur

Verstehe. :smile:

Oder doch nicht ganz, hab das jetzt interessehalber mal ausprobiert, hatte Datensätze 1 - 7, wollte zwischen 3 und 5. Erster Versuch mit und ohne Index brachte 3. Zweiter Versuch nach Löschen und Wiedereinfügen brachte 4.

Was ich jetzt nicht verstehe, vergibt er die ROWNUMs jetzt nur für Datensätze die in der Ergebnismenge (definiert durch die anderen Kriterien) drinnen sind oder für alle Datensätze die das FROM erzeugt (und war es damit Zufall, dass die ROWNUM 1 wieder in meinem Bereich lag und ich vier als Ergebnis bekommen habe)?

Warum ich da so nachbohre, ich hab diese ROWNUM erst einmal verwendet, das war ein DELETE in der Form:

LOOP
 DELETE
 FROM agg\_messages
 WHERE msg\_parent IS NULL AND msg\_deleted = 1 AND ROWNUM 

Das war gedacht um zu vermeiden, dass das Rollback-Segment überläuft (die hätte \> 1 Million Datensätze mit BLOB-Feldern löschen sollen).

D. h. da hätte mir es irgendwann passieren können, dass ich in einer Endlosschleife lande, weil die ersten Tausend Datensätze immer eigentlich gar nicht dem Selektionskriterium entsprechend, damit nichts gelöscht wird, als Abbruch der Schleife aber die Anzahl der Datensätze auf die das Kriterium insgesamt zutrifft genommen wird, also da schon noch welche da sein hätten können?




> PS: Abgesehen davon ist die Klammer nach der ORDER BY-Klausel  
> und die zweite WHERE-Klausel falsch. Das Statement sollte so  
> nicht laufen ...


Sorry, war Copy&amp:stuck\_out\_tongue\_winking\_eye:aste und ich hatte es dann nicht probiert. :smile:

Danke und Grüße, Robert

Hallo Robert!

Das Problem bei WHERE rownum… und einer ORDER BY Klausel liegt darin, daß immer zuerst die WHERE Klausel angewandt wird, dann erst die ORDER BY.
Vielleicht wird es mit diesem Beispiel leichter zu verstehen:

"SELECT \* FROM my\_table;" liefert:
col\_1 col\_2
5 Zeile1
4 Zeile2
3 Zeile3
2 Zeile4

"SELECT \* FROM my\_table WHERE rownum

somit wird auch klar, daß Deine DELETE Anweisung (zumindest diesbezüglich) genau das macht, was Du Dir erwartest (also Blöcke von 1000 rows löschen).

Gruß,
Martin

P.S.: Ich habe im Beispiel vorausgesetzt, daß das Hinzufügen der WHERE Klausel das Ergebnis bezüglich der Reihenfolge der rows nicht verändert. In Wirklichkeit liefert ...where rownum

Hi,

dauert bei mehreren millionen eintraegen doch recht lange.

das sollte es eigentlich nicht, wenn auf a ein Index liegt. Hast Du Dir mal den Execution Plan ausgeben lassen?

Versuche auch mal „…WHERE a >= [wert]“ statt mit BETWEEN, oder eine weitere Schachtelung („SELECT min(a) FROM (SELECT a … BETWEEN …)“). Beiden Varianten gebe ich allerdings nur eine geringe Chance; irgendwie glaube ich eher, dass der Index nicht verwendet wird.

Falls doch:
ALTER INDEX index_auf_a REBUILD ONLINE

Cheatah

Muss ich heute mal alles ausprobieren. :o)

Grüße, Robert

Hallo Robert,

das du das Exit mit dem Return umgehst finde ich extrem unsauber. Die If-Bedingung würde ich so schreiben:

IF SQL%NOTFOUND THEN …

Erfüllt den selben Zweck und ist sauberer. Eigentlich nur zwei Kleinigkeiten - im kommerziellen Umfeld kann es aber teuer werden. Weisst du sicherlich selber.

Gruß Janus

PS - Testfrage zum Thema Rownum (beziehen sich alle auf die EMP-Tabelle) :

Welche 3 Mitarbeiter verdienen am meisten ?
Welche 3 Mitarbeiter wurden als letztes eingestellt ?
Welche 3 Mitarbeiter kommen im Alphabet als erstens ?

Hallo Janus,

Erfüllt den selben Zweck und ist sauberer. Eigentlich nur zwei
Kleinigkeiten

Danke, werde das nächste Mal dran denken. In diesem Fall hat es sich erledigt weil der Oracle-Admin der die DB betreut gemeint hat er hängt uns einfach ein entsprechend grosses Rollback-Segment ein und wir machen ein einfaches DELETE. :o)

PS - Testfrage zum Thema Rownum (beziehen sich alle auf die
EMP-Tabelle) :

EMP-Tabelle?

Grüße, Robert