Copyright © 2014 Oracle and/or its affiliates. All rights reserved. | Volltextrecherche und mehr: Wozu man ORACLE TEXT nutzen kann Carsten Czarski Business Unit Database Oracle Deutschland B.V. & Co KG
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Volltextrecherche und mehr: Wozu man ORACLE TEXT nutzen kann
Carsten Czarski Business Unit Database Oracle Deutschland B.V. & Co KG
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Inhalt
• Oracle Text im Überblick
• Abfragemöglichkeiten – Operatoren, unscharfe Namenssuche, Progressive Relaxation, Scoring
• Hintergrundinformation – Ablauf, Komponenten, Verhalten bei DML, Preferences, Multilinguale Indizes
• Indexarten – CONTEXT, CTXCAT, Composite Domain Index (CDI)
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle TEXT: Warum macht Oracle das?
• Viele Datenhaltungs-Systeme
• Große Aufwände zur Integration
• Interaktion sehr langsam
3
Strukturierte Daten Textdokumente andere Daten
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Eine Beispielapplikation: Trefferliste
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Die Indizierung
• Unterstützung aller gängigen Datentypen – XMLTYPE, VARCHAR2, CLOB, BLOB, Database Filesystem, SecureFile
– Filter bei Binärdaten möglich
create index idx_textindex on dokument_tab (dokument) indextype is CTXSYS.CONTEXT Index created.
HINTERGRUND:
• Extensible Indexing Framework
• Spatial, TEXT, Expression Filter
• Eigene Indizes möglich
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Indextypen: CONTEXT vs. CTXCAT
• CTXCAT-Index für kleine Textfragmente optimiert (max. 20 Wörter) – In Verbindung mit Filtern auf andere Tabellenspalten
– Index ist wartungsarm (keine Synchronisierung, keine Optimierung)
• CONTEXT Index für alle Dokumentgrößen geeignet
CONTEXT CTXCAT
Indexpflege Asynchron Synchron
Dokumentgröße Unbegrenzt max. 25-30 Wörter
Operator CONTAINS CATSEARCH
Abfragesprache Alle TEXT Features Limitiert
Mixed Queries Composite Domain-Index, SDATA Sections
Sub-Indizes
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Funktionen der Volltextrecherche
• Abfrage mit SQL – CONTAINS-Funktion
– XQuery Fulltext für XML-Dokumente Oracle12c
– Kombinierbar mit relationalen Abfragen
• Relevanz-Ranking anhand Wort-Häufigkeiten – SCORE()-Funktion
• Ergebnis-Aufbereitung – Highlighting
– "Keyword-in-Context"
select score(1), dokument from dokument_tab where CONTAINS( dokument, 'Software AND Oracle', 1 )>0
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Abfragemöglichkeiten
• Logische Kombinationen ... where contains(text, 'Hund AND Katze') >0
• Wildcard-Suche ... where contains(text, 'Hu%d AND Kat_e') >0
• Namenssuche ... where contains(text, 'NDATA(name, Hunt)') >0
• Fuzzy matching ... where contains(text, '?Hunt') >0
• Multilinguale Stammsuche ... where contains(text, '$läuft') >0
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Abfragemöglichkeiten
• NEAR-Operator ... where contains(text, 'near(Hund, Katze), 4') >0
• Suche in Sektionen, Sätzen und Paragraphen (XML) ... where contains(text, 'Hund WITHIN TITEL') >0
• ISO 2788 konformer Thesaurus ... where contains(text, 'SYN(Hund,[thes]' >0)
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle Text Name Search
• Ähnlichkeitssuche, optimiert für Namen – Unterschiedliche Schreibweisen, unterschiedliche Reihenfolge Vor- und Nachname
– Sprachunabhängiges Regelwerk
– Findet mehr Treffer als "normale" Fuzzy-Suche mit "?"
– Spezielle NDATA-Sections im Index nötig tendenziell größere Indizes
select * from names where contains(name, 'NDATA(name,Tsaarski)') > 0 ID NAME ---------- ---------------------------------------- 4 Carsten Czarski
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Ergebnis-Aufbereitung: SNIPPET
• Funktion CTX_DOC.SNIPPET – Teil der SQL SELECT-Liste
– Hervorhebung konfigurierbar (Default ist <b></b>)
– Berücksichtigung von Ähnlichkeits- oder linguistische Suche
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Progressive Relaxation
• Erweiterung der Textquery – ... schrittweise ...
– ... bis die gewünschte Trefferzahl (ROWNUM) erreicht ist
select score(1), title from test_table where contains ( dokument, '<query> <textquery> <progression> <seq>Hund and Katze</seq> <seq>Hund or Katze</seq> <seq>Hund? or Katze?</seq> : and rownum <= :1
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Scoring: Relevanz Ranking
• Score Algorithmus ist eine Variante von Salton.
• Scoring nach der inversen Dokumenthäufigkeit.
• Score-bezogene Operationen auf Ergebnislisten
• Gewichtung möglich
select score(1), document from document_tab where contains(text, 'Hund', 1 )>0 order by score(1)
... where contains(text, 'Hund OR Katze*3)' >0
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Score-Algorithmus: Ausschnitt aus dem Handbuch
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
User Defined Scoring: DEFINEMERGE / DEFINESCORE
• Modifizierung des Default Algorithmus – DEFINESCORE, DEFINEMERGE Operatoren in der CONTAINS-Abfrage
• Folgende scoring expressions möglich: – DISCRETE : Term vorhanden 100, falls nicht 0
– OCCURRENCE: Anzahl der Vorkommen
– RELEVANCE: Standard-Algorithmus
– COMPLETION: Ratio für Section Suche: Anzahl der Treffer zu Anzahl aller Ausdrücke
– IGNORE: Scoring des Terms ignorieren
– LOG,ABS, ...: Rechenoperationen
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
User Defined Scoring: Beispiele
• DEFINESCORE
• DEFINEMERGE
SELECT ... FROM texttabelle
WHERE contains(dokument,
'DEFINESCORE (Umfrage, occurrence)', 1)>0
SELECT ... FROM texttabelle WHERE contains(dokument, 'DEFINEMERGE( ( (DEFINESCORE(Sport,occurrence), (DEFINESCORE(Sport,relevance * 5) ), AND, MAX )'
)>0
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Thesaurus
• Suchbegriffs-Expansion – Synonymbegriffe (SYN), Engere (NT), Weitere (BT), Übersetzungen (TR)
• Thesaurus wird in Tabellen abgelegt – Pflege mit CTX_THES
– Werkzeuge zum Bulk-Load vorhanden
– Aber: Oracle liefert keinen deutschsprachigen Thesaurus mit
select text from test_thes_tab where contains(text, 'NT(Spieler, 10, MEIN_THESAURUS)') > 0; TEXT --------------------------------------------------------------- Der Stürmer lieferte eine Glanzleistung ab.
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Einfache Performance-Regeln
• Der Idealfall: – Nur eine einzige CONTAINS Klausel
– "Mixed Queries" vermeiden oder Composite Domain Index nutzen
– Ausgabe nur der ersten 10-20 Treffer
• Unbedingt vermeiden
select score(1), dokument from dokument_tab where CONTAINS(dokument, 'Software')>0 AND CONTAINS(dokument, 'Oracle')>0
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Was ist so besonders an "Mixed Queries" ...?
• Kombination unterschiedlicher Indextechnologien
• Kostenintensiv, besonders bei unselektiven Abfragen
• Nachträgliche Sortierung ebenfalls sehr teuer
select * from dokumente
where contains(text,'Reuter')>0
and ort='Frankfurt' and monat=11
order by esdatum
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Ausführung einer Mixed Query
• Oracle TEXT Lookup für Dokumente, die "Reuter" beinhalten
• Normaler Index-Lookup bzw. Tablescan für ORT und DATUM-Filter
• Kombination der beiden Teilmengen
• Sortierung der Treffer nach Datum
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Composite Domain Index: Idee und Arbeitsweise
• Aufnahme aller Filterkriterien in den TEXT Index
• Strukturierte Spalten als SDATA Sections Support für >, <, >=, <=
• Ausführung der gesamten Query im Oracle TEXT Index
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle TEXT Indizierungsprozess
Filter Sectioner Lexer
AUTO_FILTER
Plain Text
HTML
XML
News/E-Mail
Basic – Whitespace
Themen Engine
Decompounding
alternate spelling
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Aufbau eines TEXT Index
Tabelle Inhalt
DR$ ... $I Token-Tabelle: Enthält die Tokens und Informationen über deren Vorkommen in den Dokumenten
DR$ ... $K Mapping-Tabelle ROWID DOCID
DR$ ... $N Negativliste: Enthält alle gelöschten DOCID's
DR$ ... $R Mapping-Tabelle DOCID ROWID
DR$ ... $P Substring-Index zur Unterstützung von %TOKEN Abfragen
DR$ ... $S SDATA-Tabelle – enthält strukturierte Elemente für Abfragen wie >, <, BETWEEN
DR$ ... $E Oracle12c: XQuery Fulltext – XML Namespace-Informationen
DR$ ... $G Oracle12c: Near Realtime Index
DR$ ... $D Oracle12c: Save Copy Feature
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Die Token-Tabelle ($I)
Name Null? Type ----------------- -------- ------------ TOKEN_TEXT NOT NULL VARCHAR2(64) TOKEN_TYPE NOT NULL NUMBER(3) TOKEN_FIRST NOT NULL NUMBER(10) TOKEN_LAST NOT NULL NUMBER(10) TOKEN_COUNT NOT NULL NUMBER(10) TOKEN_INFO BLOB
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle Text Ablauf
Tabelle mit Dokumenten
1 the cat sat on the mat 2 the cat in the hat 3 the hat mat
ID DOCUMENT
TOKEN DATA CAT DOC 1 POS 2 DOC 2 POS 2 SAT DOC 1 POS 3 MAT DOC 1 POS 6 DOC 3 POS 3 HAT DOC 2 POS 5 DOC 3 POS 3
$I Tabelle
the cat sat on the mat
1 2 3 4 5 6
Token bilden Stoppwörter aussondern
CAT WORD 2 SAT WORD 3 MAT WORD 6
Aggregieren
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
DOCIDs in Oracle Text
• Oracle TEXT nutzt DOCIDs – DOCIDs sind kompakter als ROWIDs
– Faktor ~10:1
$I-Tabelle
DOCID
$R-Tabelle
ROWID
document-table
Token Lookup ROWID-Lookup ROW Lookup
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle TEXT: Verhalten bei DML
• Besonderheit ... – Idealfall: In-Place-Pflege in der Token-Tabelle
– Aber: Zu teuer!
• Daher: – INSERT: PENDING-Tabelle
– DELETE: Negativliste
– UPDATE: DELETE und INSERT
• Zusätzliche Aufgaben: – Index-Synchronisierung
– Index-Optimierungen
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Near Realtime Index
• DML wird synchron in "Stage-Index" übernommen
• Stage Index hinreichend klein, um in die SGA zu passen In Memory Lookups
• Automatisches Merge des "Stage-Index" in den Hauptindex Stage-Index bleibt klein
Oracle
TEXT Index
DML auf
Tabelle Stage
Index
http://oracle-text-de.blogspot.co.uk/2013/10/oracle-text-in-oracle-12c-automatic.html
Synchron MERGE
(asynchron)
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Index konfigurieren: Preference API
• Es gibt Nutzer- und Systemdefinierte Preferences.
select distinct pre_class, pre_owner from ctx_preferences;
PRE_CLASS PRE_OWNER ------------------------------ ------------------------ DATASTORE ODD_EDITIONS STORAGE US STORAGE SH DATASTORE CTXSYS DATASTORE US ...
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Beispiele für Preference Klassen
Preference Was wird in Oracle TEXT gesteuert …?
Datastore Zu indizierende Datenquelle
Filter Umwandlung von Binärformaten in ASCII-Text
Lexer Zerlegung des Fließtexts in Tokens
Storage Physikalische Speicherung der DR$-Tabellen
Stop List Welche Wörter werden nicht indiziert?
Section Group Unterteilung von Dokumenten in Abschnitte (Sections)
Word List Linguistische Einstellungen im Index
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Beispiel: Multicolumn Datastore
• Preference definieren
• Preference anwenden
begin ctx_ddl.create_preference('my_multi','MULTI_COLUMN_DATASTORE'); ctx_ddl.set_attribute('my_multi', 'columns', 'column1, column2'); end;
create index mdata_index on products(prod_desc) indextype is ctxsys.context parameters ( 'DATASTORE my_multi SECTION GROUP my_seg MEMORY 500M' );
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Datenquelle (Datastore Preference)
• DIRECT_DATASTORE
• MULTICOLUMN_DATASTORE
• DETAIL_DATASTORE
• FILE_DATASTORE
• URL_DATASTORE
• USER_DATASTORE
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Lexer-Preference: Einstellungen für die deutsche Sprache
• Typische Einstellungen in Deutschland
begin CTX_DDL.create_preference('MEIN_LEXER','BASIC_LEXER'); CTX_DDL.set_attribute('MEIN_LEXER', 'ALTERNATE_SPELLING', 'GERMAN'); CTX_DDL.set_attribute('MEIN_LEXER', 'COMPOSITE', 'GERMAN'); CTX_DDL.set_attribute('MEIN_LEXER', 'MIXED_CASE', 'NO'); CTX_DDL.set_attribute('MEIN_LEXER', 'BASE_LETTER', 'YES'); CTX_DDL.set_attribute('MEIN_LEXER', 'INDEX_STEMS', 'GERMAN'); end;
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Tokentabelle mit Standard-Lexer
TOKEN_TEXT ---------------------------------- ALLE BESTÜRZT CLINTON DEN DER DIESEM ERNEUTER ERSTE FACKELLAUF GANGE GEHT GELD GEWINNT GEWINNZUWACHS HANSESTADT IMMER IST
TOKEN_TEXT ---------------------------------- LIVE MACHEN MEHR MESSE NAHOST NÄHER OBAMA OLYMPIA PAPST PARTEI PRÄSIDENT RÜCKT SEHEN SEINE SKANDAL SOFTWARE STEIGT
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Token-Tabelle mit eigenem Lexer
TOKEN_TEXT ---------------------------------- ALL ALLE BESTURZEN BESTURZT CLINTON DEN DER DIE DIES DIESER ERNEUEN ERNEUT ERNEUTER ERST ERSTE ERSTER FACKEL
TOKEN_TEXT ---------------------------------- GEHEN GEHT GELD GEWINN GEWINNEN GEWINNT GEWINNZUWACHS HANSE HANSESTADT IMMER IST JAHR JAHREN JUNG JUNGSTEN KAMPF KRIMINALITAT
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Stopwortliste erzeugen und nutzen
• Oracle-Skript aus Ausgangsbasis - eigene Stopwörter hinzufügen
• CREATE INDEX mit Parameter STOPLIST
begin ctx_ddl.create_stoplist('DEFAULT_STOPLIST'); ctx_ddl.add_stopword('DEFAULT_STOPLIST', 'ab'); ctx_ddl.add_stopword('DEFAULT_STOPLIST', 'aber'); ctx_ddl.add_stopword('DEFAULT_STOPLIST', 'allein'); : end;
create index idx_text on texttabelle (dokument) indextype is ctxsys.context Parameters ('stoplist de_stoplist')
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Suche in Dokumentabschnitten: Section Groups
• Abschnitte gekennzeichnet durch Tags (XML) – Schachtelung möglich
– Keine strenge Hierarchie erforderlich
– XML-Anforderungen gelten nicht
• Abbildung im Textindex durch Section Groups – Unterschiedliche Typen (Field, Zone)
– Unterschiedliche Indizierungsvarianten
– Suche mit WITHIN
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle TEXT und XML
• XML_SECTION_GROUP – Explizite Indizerung von XML-Tags und deren Inhalt
– Einfache WITHIN-Suche möglich (keine PATH-Syntax)
• AUTO_SECTION_GROUP – Indizierung des gesamten Dokumentes
– Expliziter Ausschluß von Abschnitten möglich
– Einfache WITHIN-Suche möglich (keine PATH-Syntax)
• PATH_SECTION_GROUP – Indizierung des gesamten Dokuments
– Keine Ausschlüsse möglich (außer USER DATA STORE)
– Erweiterte Abfragesyntax (PATH)
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Suche in XML-Dokumenten select id from xml_text where contains(doc, 'Carsten within (VORNAME)') > 0; ID ---------- 1 1 Zeile wurde ausgewählt. select id from xml_text where contains(doc, 'Carsten') > 0; ID ---------- 1 1 Zeile wurde ausgewählt. select id from xml_text where contains(doc, 'Carsten within (NAME)') > 0; Es wurden keine Zeilen ausgewählt
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
XQuery Fulltext: Setup
• Volle Unterstützung für XML-Datenmodell – Namespace-Support
– Standardkonforme Abfragen XQuery Fulltext
• Indexerstellung mit PATH_SECTION_GROUP und XML_ENABLE=TRUE begin ctx_ddl.create_section_group('my_sg_xquery', 'PATH_SECTION_GROUP'); ctx_ddl.set_sec_grp_attr('my_sg_xquery', 'xml_enable', 'true'); end; / sho err create index ft_tabxml on tab_xml (docs) indextype is ctxsys.context parameters ('section group my_sg_xquery') /
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
XQuery Fulltext: Abfragen
• Nutzung von XMLExists und XQuery-Syntax
• Oracle TEXT CONTAINS wird hier nicht genutzt
• XMLExists ist eine Funktion der XMLDB
• Kombination mit anderen XQuery-Konstrukten möglich
SELECT id FROM tab_xml WHERE XMLExists('declare namespace ns="http://mynamespaces.com/ns2"; //ns:tag[. contains text "text"]' PASSING docs)
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle TEXT Unterstützung für JSON
• Erstellung eines Oracle TEXT Index für JSON
42
CREATE INDEX po_search_idx ON po_json (json) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ( 'section group CTXSYS.JSON_SECTION_GROUP SYNC (ON COMMIT)' ) / Index wurde erstellt.
12.1.0.2
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Oracle TEXT Unterstützung für JSON
• Erstellung eines Oracle TEXT Index für JSON
43
select filename from po_json WHERE json_textcontains( json, '$.PurchaseOrder.LineItems.LineItem.Description', 'Magic' ); TURNER-20021009123338565PDT.js CLARK-2001112712105223PST.js :
12.1.0.2
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Weitere Informationen
• Deutschsprachiges Blog zu Oracle TEXT http://oracle-text-de.blogspot.com
• Handbücher (Dokumentation) http://docs.oracle.com – Oracle TEXT Application Developers Guide
– Oracle TEXT Reference
• Informationen zur Oracle-Datenbank auf Deutsch – http://tinyurl.com/OracleBUDB
– http://twitter.com/OracleBUDB
Copyright © 2014 Oracle and/or its affiliates. All rights reserved. |
Fragen & Antworten
[email protected] http://tinyurl.com/apexcommunity http://sql-plsql-de.blogspot.com http://oracle-text-de.blogspot.com http://oracle-spatial.blogspot.com http://plsqlexecoscomm.sourceforge.net http://plsqlmailclient.sourceforge.net Twitter: @cczarski @oraclebudb