Posts mit dem Label count_hits werden angezeigt. Alle Posts anzeigen
Posts mit dem Label count_hits werden angezeigt. Alle Posts anzeigen

Donnerstag, 18. Oktober 2012

Treffer zählen:COUNT_HITS und Mixed Queries zusammen!

Vor nun schon fast vier Jahren hatten wir bereits ein Blog-Posting zum Thema "Treffer zählen mit Oracle TEXT" veröffentlicht. Zusammengefasst kann man sagen, dass man nach Möglichkeit immer mit CTX_QUERY.COUNT_HITS arbeiten sollte. Diese Prozedur stellt sicher, dass die Zählung ausschließlich im Textindex stattfindet und dass (teure) Zugriff auf die Basistabelle unterbleiben.
set serveroutput on

declare
  v_number number;
begin
  v_number := ctx_query.count_hits(
    index_name => 'MY_FULLTEXT_IDX',
    text_query => 'oracle and text',
    exact =>      true
  );
  dbms_output.put_line('Anzahl Treffer: '||v_number);
end;
/
 
Anzahl Treffer: 2657
Doch was ist, wenn der Oracle Textindex mit dem in Oracle11g neuen Feature Composite Domain Index erstellt wird ...?
CREATE INDEX comp_ind ON customers(cust_first_name)
INDEXTYPE IS ctxsys.context
FILTER BY cust_id, cust_year_of_birth
ORDER BY cust_year_of_birth
Der Composite Domain Index nimmt die in der FILTER BY-Klausel angegebenen Spalten mit in den Volltextindex auf und führt mixed Queries wie die folgende dann allein mit Hilfe des Oracle TEXT Index aus.
SELECT cust_id FROM customers
WHERE contains (cust_first_name, 'A% or D% or N% or B%') > 0 AND cust_year_of_birth > 1970 
/
Wenn nun die Treffer gezählt werden sollen, tut man sich bei der Nutzung von CTX_QUERY.COUNT_HITS etwas schwer ... denn wo soll man das Filterkriterium cust_year_of_birth > 1970 einsetzen ...?
FUNCTION COUNT_HITS RETURNS NUMBER
 Argument Name                  Typ                     In/Out Defaultwert?
 ------------------------------ ----------------------- ------ --------
 INDEX_NAME                     VARCHAR2                IN
 TEXT_QUERY                     VARCHAR2                IN
 EXACT                          BOOLEAN                 IN     DEFAULT
 PART_NAME                      VARCHAR2                IN     DEFAULT
Die Lösung ist einfacher, als man denkt: Denn für jede der in der FILTER BY-Klausel angegebenen Spalten bildet Oracle TEXT eine SDATA-Section gleichen Namens. In diesem Fall haben wir also die SDATA Sections CUST_YEAR_OF_BIRTH und CUST_ID. Und diese lässt sich nun auch als Teil der CONTAINS-Abfrage explizit ansprechen. Die CONTAINS-Abfrage mit SDATA-Section sieht dann so aus ...
'A% or D% or N% or B% and SDATA(cust_year_of_birth > 1970) 
Eingesetzt in CTX_QUERY.COUNT_HITS ...
set serveroutput on

declare
  v_number number;
begin
  v_number := ctx_query.count_hits(
    index_name => 'COMP_IND',
    text_query => 'A% or D% or N% or B% and SDATA(cust_year_of_birth > 1970)',
    exact =>      true
  );
  dbms_output.put_line('Anzahl Treffer: '||v_number);
end;
/
 
Anzahl Treffer: 1623
Mehr Information in der Oracle Dokumentation - TEXT Reference.

Montag, 8. Dezember 2008

Ergebnisse zählen: Nicht mit count(*), sondern mit COUNT_HITS!

Wenn man Oracle TEXT in einer Applikation nutzt und Abfragen mit der CONTAINS-Funktion durchführt, möchte man fast immer auch die Anzahl der Treffer auf der Ergebnisseite anzeigen. Und der erste, naheliegende Gedanke ist, hierfür ein SELECT COUNT(*) zu verwenden - die Abfrage findet ja auch mit einem SELECT statt.
select count(*) from dokument_tab where contains(dokument, 'Bundeskanzler') > 0
Gerade bei Oracle TEXT ist diese Variante jedoch sehr ineffektiv - denn die Datenbank muss hierfür sowohl auf den Volltextindex als auch auf die Tabelle zugreifen. Besser ist es, die dafür vorgesehene Funktion COUNT_HITS im PL/SQL-Paket CTX_QUERY zu nutzen.
set serveroutput on

declare
  v_number number;
begin
  v_number := ctx_query.count_hits(
    index_name => 'MY_FULLTEXT_IDX',
    text_query => 'oracle and text',
    exact =>      true
  );
  dbms_output.put_line('Anzahl Treffer: '||v_number);
end;
/
 
Anzahl Treffer: 2657
Man muss den Namen des Index kennen, um die Funktion nutzen zu können; mit der Dictionary View CTX_USER_INDEXES ist dieser aber leicht zu ermitteln. Interessant ist noch der Parameter exact - gibt man hier false an, so arbeitet die Funktion schneller, dafür ungenauer: Seit der letzten Indexoptimierung gelöschte und veränderte Dokumente werden dann nicht berücksichtigt; der Wert ist also zu hoch. Direkt nach einer Indexoptimierung liefern sowohl exact => true als auch exact => false gleiche Ergebnisse zurück. In allen Fällen ist CTX_QUERY.COUNT_HITS schneller als ein SELECT COUNT(*).
Mehr Information in der Oracle Dokumentation - TEXT Reference.

Beliebte Postings