Eine sehr wichtige Eigenschaft jedes Textindex ist das TRANSACTIONAL Keyword, welches
seit Oracle10g verwendet werden kann.
Normalerweise ist es ja so, dass Änderungen an der Dokumenttabelle im Index nicht sofort
sichtbar werden, sondern erst nach dem Index Sync. Das kann man sehr schön in der
View CTX_USER_PENDING nachvollziehen.
SQL> select PND_INDEX_NAME, PND_ROWID, PND_TIMESTAMP from ctx_user_pending; PND_INDEX_NAME PND_ROWID PND_TIMESTAMP ------------------------------ ------------------ ------------------- IDX_DOKUMENT_VOLLTEXT AAAiPsAAEAAAjUlAAD 16.09.2008 10:18:35 IDX_VOLLTEXT_2 AAAiPsAAEAAAjUkAAA 29.07.2008 11:12:59 IDX_VOLLTEXT_2 AAAiPsAAEAAAjUlAAD 16.09.2008 10:18:36 IDX_VOLLTEXT_2 AAAiPsAAEAAAjUmAAD 29.07.2008 10:50:37 IDX_VOLLTEXT_2 AAAiPsAAEAAAjUmAAE 29.07.2008 10:59:23
In einer Volltextrecherche sind diese Dokumente normalerweise nicht sichtbar; sie
sind noch nicht in den Index synchronisiert. Doch was tut man, wenn die Anforderung
besteht, dass alle Dokumente sofort durchsuchbar sein müssen ...?
Man könnte den Index nach jedem COMMIT synchronisieren; damit wäre die Anforderung
erstmal erfüllt ... und es gibt sogar einen Parameter dafür: Beim CREATE INDEX kann
als Parameter SYNC ON COMMIT mitgegeben werden. Das hat aber einen gewichtigen
Nachteil:
Beim Synchronisieren (CTX_DDL.SYNC_INDEX) wird ebenfalls Wert auf möglichst
kurze Laufzeit gelegt. Die neuen Informationen (die Tokens des neuen Dokumentes)
werden also nicht an die Stellen in den Index eingepflegt, wo es für die Abfrageperformance optimal wäre, sondern
dort, wo es am schnellsten geht: quasi "ans Ende" des Index. Die hinsichtlich Abfrageperformance
"optimale" Struktur
wird erst durch das Optimieren (CTX_DDL.OPTIMIZE_INDEX) erzeugt.
Eine Synchronisierung nach jedem Commit bedeutet also, dass der Index mit jedem
Commit weiter "fragmentiert" - die Abfrageperformance also recht schnell immer schlechter wird. Als
Faustregel kann man festhalten, dass eine Synchronisation mit so vielen Dokumenten
wie möglich stattfinden sollte - auf jeden Fall aber mit mehr als einem.
Das sieht nach einem Dilemma aus: Wenn nun (siehe oben) die Anforderung besteht, dass ein
neues Dokument sofort durchsuchbar sein soll, müssten wir ja nach jedem COMMIT synchronisieren -
das wollen wir aber nicht, weil der Index dann zu schnell fragmentiert. Und genau hier
greift der Parameter TRANSACTIONAL des Volltextindex. Ein transaktionaler Index
wird wie folgt erzeugt:
create index idx_volltext on dokumente_tabelle (spalte)
indextype is CTXSYS.CONTEXT
parameters ('TRANSACTIONAL')
Bei Volltextabfragen mit der CONTAINS-Funktion auf diesen Index werden nun auch
die noch gar nicht im Index befindlichen Dokumente gefunden. Wird der Parameter gesetzt,
so durchsucht Oracle die noch nicht synchronisierten Dokumente (CTX_USER_PENDING) zur
Abfragezeit on-the-fly.
Der Vorteil ist nun, dass man nicht mehr "den Druck hat", den Index sofort nach
Einfügen eines Dokumentes zu synchronisieren - denn es ist ja auffindbar. Man kann
sich nun ein geeignetes Synchronisierungsintervall überlegen, welches die Indexfragmentierung
einerseits in Grenzen hält und andererseits häufig genug synchronisiert, so dass nicht
zuviele Dokumente on-the-fly durchsucht werden müssen. Denn eins ist auch klar: Die
Suche im Index ist auf jeden Fall günstiger als die on-the-fly Suche durch die
noch nicht synchronisierten Dokumente.
Generell kann man sagen, dass der Parameter TRANSACTIONAL ab Oracle10g eine
gute Sache ist - man kann ihn eigentlich generell setzen. Das Finden eines guten Intervalls zum
Synchronisieren und zum Optimieren (also das Finden einer guten Strategie für die Indexwartung)
bleibt jedoch weiterhin eine wichtige Aufgabe in einem Oracle TEXT Projekt.