Hi Cheatah,
10% ist schon fast zu schlecht, um den Index überhaupt
erst anzulegen.
Kommt auf die Daten an. Gerade wenn Du eine Handvoll
verschiedener Typen hast, sind i.d.R. einige dabei, die
mehr als 10% beanspruchen.
Yep. Aber wenn es _im Mittel_ 10% der Treffer sind, dann nützt
der Index weniger, als er kostet.
Würde ich "analyze" implementieren, dann würde ich auf
jeden Fall speichern:
Wie oft würdest Du diese Werte aktualisieren?
Ich - gar nicht. "analyze" ist ein Kommando, welches der
Betreiber des RDBMS ausführt oder auch nicht.
Diese Entscheidung kann ich ihm nicht abnehmen, weil ich sein
Betriebskonzept nicht kenne.
Wenn Du nicht gerade 24/7 denken mußt (der Dir wenigstens in
bestimmten low-traffic-Zeiten etwas mehr CPU-Last zumuten
kannst), dann sind die housekeeping-Phasen genau dazu nützlich,
um Berechnungen durchzuführen, die besser dort als während der
online-Wartezeit des Benutzers stattfinden sollten.
Und in solchen Phasen ist ein "analyze" gut platziert.
Schon einen Index aktuell zu halten kostet Rechenzeit (und
einiges an Speichermanagement). Eine Analyse kann jedoch nur
schwerlich inkrementell gemacht werden, da sie auch darauf
beruht, gerade detaillierte Daten _nicht_ zu speichern - im
(dumm implementierten) Extremfall müsste jeder INSERT und
jedes UPDATE zu einer neuen Analyse führen.
Yep. Aber die Aussage darüber, wie gut ein Index projeziert
und welche drei Werte die Super-GAUs sind, ändert sich nicht
innerhalb weniger Stunden.
Natürlich veralten die Werte von "analyze" ständig - aber eben
nur langsam. Wie oft man sie refreshen möchte, das hängt von
der Änderungsfrequenz des Tabellen-Inhalts ab ... das können
Stunden sein, aber auch Tage oder Wochen.
Und bei einem Indexzugriff würde ich diese Liste prüfen,
um einen Indexzugriff für diese "pathologisch
schlechten" Werte zu verhindern.
Wie wäre es mit ANALYZE INDEX? ;-)
Ich habe jetzt überhaupt nicht an real existierende Imple-
mentierungen gedacht, sondern an das Prinzip als solches.
Mich interessieren in diesem Kontext keine Produkte, sondern
Algorithmen ...
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'BAK_CATEGORY'
2 1 INDEX (RANGE SCAN) OF 'TESTINDEX' (NON-UNIQUE)
Also, der Index wird verwendet.
Ja - für die erste der beiden WHERE-Klauseln. Aber nicht für die zweite. (Wie denn auch? ;-)
Ganz einfach: Die zweite Spalte befindet sich im Range der
ersten. "x%" ist ein vollständiger Bereich des Index von A
bis B, und darin wird nach allen "y%" der zweiten Spalte
gesucht.
Und zwar wie?
Einen separat nach der zweiten Spalte sortierten Indexbaum nur
genau für diesen Treffer-Range des ersten kann es nicht geben
(wer sollte den wann angelegt haben?) - und wenn es den nicht
gibt, dann kann ich nur noch sämtliche gefundenen Indexwerte
mit einem "full indexrange scan" abfragen.
Das bedeutet für mich aber nicht, diesen Index "zu benutzen",
d. h. seine eigene Projektivität zu verwenden.
Ob ich jetzt innerhalb des Indexbaums einen Vergleich mit dem
Inhalt des zweiten Indexfeldes habe oder ob ich dafür auf die
row-Daten zugreifen muß, daß ist nur ein konstanter Faktor
mehr. Aber von konstanten Faktoren rede ich im Zusammenhang
mit Indexen normalerweise gar nicht ...
Klar erkennt Oracle, daß es mit dem zweispaltigen Index
wenigstens die erste der beiden Spalten adressieren kann
- aber die zweite nicht, weil es dafür einen String-Match
über ein concat beider Spaltenwerte machen müßte, und das
geht nicht wegen der wildcard am Ende der ersten WHERE-
Klausel.
Soweit ich informiert bin, können die Spalten im Index klar
voneinander getrennt werden, und zwar ohne Performance-
verlust.
Ich kann mir die erforderliche Datenstruktur nicht vorstellen.
Das Wissen, um sie zu berechnen, kann nicht existiert haben.
Zumindest wenn ich nur die beiden indizierten Spalten
selektiere, wird der Table Access By Rowid auch weggelassen.
Ergo scheint die Prüfung nichts weiter als den Index zu
brauchen.
Das ist wahr - das meinte ich aber nicht.
Sicher sparst Du den Zugriff auf die row-Daten - aber innerhalb
des Teilbaums der Treffer des ersten WHEREs macht das RDBMS
eine (langsame) Variante eines full table scans (weil es
zusätzlich auch noch in der Baumstruktur herum turnen muß) -
und keinen Baum-Abstieg zur gezielten _weiteren_ Reduzierung
der Treffermenge (weil eben kein Baum existiert, der nach
dem entsprechenden Kriterium sortiert sein könnte).
Viele Grüße
Michael