Filter-Preferences werden mit dem CREATE INDEX oder ALTER INDEX Statement erzeugt. Man sollte sich dabei nicht auf System Preferencen verlassen, sondern den Filter immer beim Anlegen des Index mitangeben. Folgende Filter Typen existieren:
- CHARSET_FILTER: Character Set Konvertierung
- AUTO_FILTER: Für formatierte Dokumente
- NULL_FILTER: Kein Filter ist erforderlich, nützlich für Plain Text, HTML und XML
- MAIL_FILTER: Transformiert RFC-822 und RFC-2045 Nachrichten in indizierbaren Text
- USER_FILTER: Externer Filter für benutzerdefinertes Filtern
- PROCEDURE_FILTER: Benutzerdefiniertes Filtern definiert über eine Prozedur
Hier im Blog gebe ich Beispiele für NULL_FILTER, AUTO_FILTER und den USER_FILTER. Weitere Beispiele dazu finden sich im Handbuch.
Zuerst wird eine Tabelle erzeugt, die Dokumente im Format Powerpoint, PDF, HTML und ASCII enthält.
drop table filter_test; create table filter_test(id number primary key, docs blob);
Zum Laden verwende ich den SQL *Loader. Die CTL Datei sieht folgendermassen aus:
LOAD DATA INFILE 'filter_load.dat' INTO TABLE null_filter FIELDS TERMINATED BY ',' (id SEQUENCE (MAX,1) , ext_fname FILLER CHAR(50), docs LOBFILE(ext_fname) TERMINATED BY EOF)
Die filter_load.dat Datei hat folgende Inhalte.
snaps.sql powerp.pptx plain.txt replay.html one_page.pdf
Im ersten Beispiel wird ein Index mit Filter Preference NULL_FILTER erzeugt. Um zu überprüfen, ob im Index Create Prozeß keine Fehler passiert sind, schalte ich Logging ein und überprüfe den Index nach dem Anlegen mit CTX_USER_INDEX_ERRORS.
drop index filter_test_idx force; execute CTXSYS.CTX_ADM.SET_PARAMETER ('LOG_DIRECTORY','/tmp'); exec CTX_OUTPUT.START_QUERY_LOG('filterlog'); create index filter_test_idx on filter_test ( docs ) indextype is ctxsys.context parameters ('FILTER ctxsys.NULL_FILTER'); execute CTX_OUTPUT.END_QUERY_LOG; SQL> select * from ctx_user_index_errors; no rows selected
Nun wird das Ergebnis überprüft. Um einen Einruck von dem Inhalt der Ergebnismenge zu bekommen, verwende ich CTX_DOC.SNIPPED. Die REGEXP_REPLACE Funktion macht das Ergebnis lesbarer und eliminiert die überflüssigen Leerzeilen.
SQL> execute ctx_doc.set_key_type('ROWID'); SQL> select id, regexp_replace(ctx_doc.snippet ('FILTER_TEST_IDX', rowid, 'plain or OLTP or replay or snapshot or SPA or REPLAY',starttag=>'###',endtag =>'###'),'\s+',' ') snippet from filter_test where contains ( docs, 'plain or OLTP or replay or snapshot or SPA or REPLAY') > 0; ID ---------- SNIPPET -------------------------------------------------------------------------------- 1 hh24:mi') from dba_hist_###snapshot### order by BEGIN_INTERVAL_TIME 3 dies ist ein ###plain### text 4 performance of a workload ###replay### against the performance of...The f irst ###replay### would try to mimic the captured
Wie zu erwarten, enthält das Ergebnis die Dokumente snaps.sql (mit 1), plain.txt (mit 2) und replay.html (mit 3).
Nun verwenden wir den AUTO_FILTER. Das Vorgehen ist ähnlich wie oben, nur die FILTER Preference lautet nun AUTO_FILTER.
drop index filter_test_idx force; execute CTXSYS.CTX_ADM.SET_PARAMETER ('LOG_DIRECTORY','/tmp'); execute CTX_OUTPUT.START_QUERY_LOG('filterlog'); create index filter_test_idx on filter_test (docs) indextype is ctxsys.context parameters ('FILTER ctxsys.AUTO_FILTER'); execute CTX_OUTPUT.END_QUERY_LOG; SQL> select * from ctx_user_index_errors; no rows selectedNun wird wieder das Ergebnis selektiert.
SQL> execute ctx_doc.set_key_type('ROWID'); SQL>select id, regexp_replace(ctx_doc.snippet ('FILTER_TEST_IDX', rowid, 'plain or OLTP or replay or snapshot or SPA or REPLAY',starttag=>'###',endtag =>'###'),'\s+',' ') snippet from filter_test where contains ( docs, 'plain or OLTP or replay or snapshot or SPA or REPLAY') > 0; ID ---------- SNIPPET -------------------------------------------------------------------------------- 1 hh24:mi') from dba_hist_###snapshot### order by BEGIN_INTERVAL_TIME 2 Sesssions und Calls ###OLTP###-Datenbanken mit ca.12.000...Siehe Enhancem ent Request ?7523016: ###REPLAY### REPORTS ORA-933 ON SET ROLE 3 dies ist ein ###plain### text 4 performance of a workload ###replay### against the performance of...The f irst ###replay### would try to mimic the captured 5 2) Before using the ###SPA### or Database Replay, understand...3) Perform STS Capture for ###SPA### & workload capture for Database
Es werden nun alle Dokumente gefiltert, indiziert und gefunden. Möchte man einen Überblick über alle unterstützten Formate erhalten, kann man dies im Handbuch nachschlagen.
Nun kommen wir zum letzten Beispiel - einem USER_FILTER. Hierzu ist ein Programm notwendig, das beim Filtern für jede Zeile ausgeführt wird. Explizit wird nun eine Preference MY_FILTER mit einem speziellen Attribut erzeugt, das den Programmnamen festlegt - hier upper.pl
execute ctx_ddl.drop_preference('my_filter'); BEGIN ctx_ddl.create_preference ('my_filter', 'user_filter'); ctx_ddl.set_attribute ('my_filter', 'command', 'upper.pl'); END; / PL/SQL procedure successfully completed.Das Programm ist ein Perl-Programm, das den Text in Großbuchstaben konvertiert. Es muß unbedingt im Verzeichnis $ORACLE_HOME/ctx/bin zu finden sein.
#!/usr/bin/perl open(IN, $ARGV[0]); open(OUT, ">".$ARGV[1]); while () { tr/a-z/A-Z/; print OUT; } close (IN); close (OUT);
Nun wird der Index erzeugt.
drop index filter_test_idx force; create index filter_test_idx on filter_test (docs) indextype is ctxsys.context parameters ('filter my_filter'); SQL> select * from ctx_user_index_errors; no rows selected
Das Ergebnis sieht dann folgendermassen aus.
SQL> select id, regexp_replace(ctx_doc.snippet ('FILTER_TEST_IDX', rowid, 'plain or OLTP or replay or snapshot or SPA or REPLAY',starttag=>'###',endtag =>'###'),'\s+',' ') snippet from filter_test where contains ( docs, 'plain or OLTP or replay or snapshot or SPA or REPLAY') > 0; ID ---------- SNIPPET -------------------------------------------------------------------------------- 4 CAPTURE VS. ###REPLAY### ...PERFORMANCE OF A WORKLOAD ###REPLAY### AGAINST THE PERFORMANCE OF...CAPTURED SYSTEM, WHILE "###REPLAY###" REFERS TO THE REPLAYED WORKLOAD.