どのようにOracle全文インデックスを使用するとより良いですか?

9870 ワード

自ら抜け出す 
http://www.cnblogs.com/tracy/archive/2010/10/20/1856480.html
 
Oracle text機能を使わないで、Oracleデータベースでテキストを検索する方法もたくさんあります。標準のINSTR関数とLIKEオペレータを使って実現できます。

SELECT *FROM mytext WHERE INSTR (thetext, 'Oracle') > 0;

SELECT * FROM mytext WHERE thetext LIKE '%Oracle%';
多くの場合、instrとlikeを使用するのは理想的で、特に小さいテーブルだけを検索する場合が多いです。しかし、これらのテキストの位置付けの方法によって、全表スキャンがもたらされ、資源にとっては比較的に高価で、実現される検索機能も非常に限られています。そのため、膨大な量のテキストデータを検索する場合、oralceで提供された全文検索機能を使って全文検索のステップを作成することを提案します。データベースの役割を確認し、設定します。まず、データベースにCTXSYSユーザーとCTXAPPの役割があるかどうかを確認します。このユーザとキャラクターがないと、あなたのデータベース作成時にintermedia機能がインストールされていないことを意味します。この機能をインストールするためにデータベースを変更しなければなりません。デフォルトのセットアップの場合、ctxsysはユーザがロックされていますので、先にctxsysのユーザを有効にします。手順二はctxsysユーザーの下でctx_を権限を与えます。ddlの実行権限は全文索引を使用するユーザに与えられます。例:
grant execute on ctx_ddl to pomoho;
ステップ3ワードアナライザを設定します。
Oracleは全文検索を実現します。その仕組みはとても簡単です。つまり、Oracle特許の語法解析器によって、文章中のすべての表意ユニット(Oracleをtermという)を探し出し、drドルで始まる一連の表に記録し、同時に当該termの出現する位置、回数、hash値などの情報を記録する。検索の際、Oracleはこのグループから該当するtermを検索し、その出現頻度を計算し、あるアルゴリズムに基づいてドキュメントごとのスコア(score)、いわゆる「マッチング率」を計算します。lexerはこのメカニズムの核心であり、全文検索の効率を決定している。Oracleは異なる言語に対して異なるlexerを提供していますが、私達は通常その中の三つを使用できます。
n  baic_lexer:英語に対して。スペースや句読点によって英語の単語を文から分離したり、頻度が高すぎて検索の意味がなくなった単語を自動的に「ゴミ」として処理することができます。if、isなど、処理の効率が高いです。しかし、このlexerは中国語に応用すると多くの問題があります。スペースと句読点しか認識していないため、中国語の文の中には通常スペースがありません。「中国人民が立ち上がった」という言葉を例にとって、baic_lexerが分析した結果、「中国人民は立ち上がった」というtermしかありませんでした。この時点で「中国」を検索すると、内容が検索できなくなります。
n  chinese.vgram_.lexer:専門の中国語解析器は、すべての漢字文字セット(ZHS 16 CGB 231280 ZHS 16 GBK ZHT 32 EUC ZHT 16 BIG 5 ZHT 32 TRIS ZHT 16 MSWIN 950 ZHT 16 HKSCS UTF 8)をサポートしています。このアナライザは字の単位で中国語の文を分析します。中国人民が立ち上がったという言葉は、次のように分析されます。「中」、「中国」、「国人」、「人民」、「民立」、「立ち上がって」、「来た」、「了」。このような分析方法は、アルゴリズムの実現が簡単で、「一網打尽」を実現することができますが、効率はあまり良くないことが分かります。
n  chinese.lexer:これは新しい中国語のアナライザです。utf 8文字セットだけをサポートします。上ですでに見ましたが、chinese vgram lexerという分析器は常用する中国語の語彙を知らないので、分析するユニットは非常に機械的で、上の「民駅」のように、「立ち上がって」は中国語の中で単独で現れないので、このtermは意味がなく、かえって影响の効率がいいです。chinese.lexerの最大の改善は、このアナライザが中国語で使われている語彙の大部分を認識することができるので、文をより効率的に分析することができます。しかし、それはutf 8だけをサポートしています。もしあなたのデータベースがzhs 16 gbk文字セットなら、不器用なChinese vgram lexerしか使えません。 何も設定しないと、OracleがデフォルトでBaic_を使用します。この解析器はlexerです。どのlexerを使うかを指定します。
第一に、現在のユーザの下でpreferenceを作成します。

exec ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer');

第二.   全文索引を作成する際に使用するlexerを指定する:

CREATE INDEX myindex ON mytable(mycolumn) indextype is ctxsys.context

parameters('lexer my_lexer');

このように作成された全文検索インデックスは、chinese_を使用します。vgram_.lexerをアナライザとします。
ステップ4インデックスの作成
以下の文法で全文索引を作成します。

CREATE INDEX [schema.]index on [schema.]table(column) INDEXTYPE IS ctxsys.context [ONLINE]

LOCAL [(PARTITION [partition] [PARAMETERS('paramstring')]

[, PARTITION [partition] [PARAMETERS('paramstring')]])]

[PARAMETERS(paramstring)] [PARALLEL n] [UNUSABLE]; :

CREATE INDEX ctx_idx_menuname ON pubmenu(menuname)

indextype is ctxsys.context parameters('lexer my_lexer')

ステップ5インデックスを使う
全文索引を使うのは簡単です。
select*from pubmenu where contains(menuname、'アップロード画像')>0
全文索引の種類
作成されたOracle Textインデックスは、ドメインインデックス(domain index)と呼ばれ、4種類のインデックスタイプを含む。
l CONTEXT
2 CTXCAT
3 CTXRULE
4 CTXXPATH
あなたのアプリケーションとテキストデータの種類によって、どちらかを選択してもいいです。
複数フィールドに全文索引を作成
多くの場合、複数のテキストフィールドから条件を満たすレコードを検索する必要があります。この場合、複数のフィールドに対する全文インデックスを作成する必要があります。例えば、pmhsubjectsのsubjectname(特定のテーマ名)とbrienfintroの全文検索は、以下の手順で行います。
Ø  複数フィールドインデックスのpreferenceを提案します。
ctxsysで登録し、実行します。

EXEC ctx_ddl.create_preference(' ctx_idx_subject_pref',

'MULTI_COLUMN_DATASTORE');

Ø preference ( ctxsys )

EXEC ctx_ddl.set_attribute(' ctx_idx_subject_pref ','columns','subjectname,briefintro');

Ø CREATE INDEX ctx_idx_subject ON pmhsubjects(subjectname)

INDEXTYPE ISctxsys.CONTEXT PARAMETERS('DATASTORE ctxsys.ctx_idx_subject_pref lexer my_lexer') Ø select * from pmhsubjects where contains(subjectname,' ')>0

全文索引のメンテナンス
CTXSYSS.CONTEXTインデックスについては、アプリケーションがベーステーブルをDMML操作した後、ベーステーブルのインデックスを維持する必要があります。索引の維持には、索引の同期とインデックスの最適化が含まれます。
インデックスが作成された後、私達はこのユーザーの下でOracleが自動的に次のいくつかのテーブルを生み出すことができます。
DR$myindex$I、DR$myindex$K、DR$myindex$R、DR$myindex$Nの中でIテーブルが一番重要です。この表を調べて、どんな内容がありますか?
SELECT token_text, token_count FROM dr$i_rsk1$I WHERE ROWNUM <= 20;
ここではリストにしないで照会してもらいました。この表に保存されているのはつまりOracleがあなたのドキュメントを分析した後、ここに作成されたtermが記録されています。ここにはtermの出現位置、回数、hash値などが含まれています。文書の内容が変わったら、このI表の内容もそれに応じて変えなければならないと思います。Oracleは全文検索をする時に正確に内容を検索することができます。これは、sync(同期)とoptimize(最適化)を使います。
同期(sync): 新しいtermをIテーブルに保存します。
最適化(optimize): I表のゴミは、主に削除されたtermをI表から削除します。
基本テーブルのインデックスされたドキュメントがinsert、udate、delete操作された場合、ベーステーブルの変更は、同期インデックスにすぐに影響を及ぼしません。ビューCTX_を確認できます。USER_PENDINGは対応する変更を確認します。たとえば:
SELECT pnd_index_name, pnd_rowid,
TO_CHAR (pnd_timestamp, 'dd-mon-yyyy hh24:mi:ss') timestamp
FROM ctx_user_pending;

: PND_INDEX_NAME                 PND_ROWID          TIMESTAMP ------------------------------ ------------------ -------------------- MYINDEX                        AAADXnAABAAAS3SAAC 06-oct-1999 15:56:50

同期と最適化方法:Oracleから提供されるctx_を使用できます。ddlパッケージの同期とインデックスの最適化
一.  CTXCATタイプのインデックスでは、ベーステーブルをDMML操作すると、Oracleはインデックスを自動的に維持する。ドキュメントの変更はすぐに索引に反映されます。CTXCATは事務形の索引である。
インデックスの同期
ベーステーブルに挿入、変更、削除後にインデックスを同期させます。sync同期インデックスの使用を推奨します。構文:
ctx_ddl.sync_index(
idx_name IN VARCHAR2 DEFAULT NULL
memory IN VARCHAR2 DEFAULT NULL,
part_name IN VARCHAR2 DEFAULT NULL
parallel_degree IN NUMBER DEFAULT 1); 
idx_name       
memory               。       DEFAULT_INDEX_MEMORY 。
大きなメモリを指定するとインデックス効率とクエリ速度が速くなります。インデックスには小さな破片があります。 パーティーnameはどのパーティションインデックスを同期させますか? parallel_degreeパラレル同期インデックス。平行度を設定します
たとえば:
同期インデックスmyindex:Exec   ctx_ddl.sync_index('myindex')
提案を実施する:oracleのjobでインデックスを同期することを提案する。
インデックスの最適化
常にインデックスを同期させると、CONTEXTインデックスに破片が発生します。インデックスの断片がクエリの応答速度に大きく影響します。定期的にインデックスを最適化して、デブリを減少させ、インデックスサイズを減少させ、クエリの効率を向上させることができます。 テキストが表から削除されると、Oracle Textは削除されたドキュメントをマークしますが、インデックスはすぐには変更されません。したがって、この文書情報については、不必要な空間を占めており、クエリに追加のオーバーヘッドをもたらしている。FULLモードでインデックスを最適化し、インデックスから古い情報を無効にしてください。この過程をゴミ処理といいます。表のテキストデータを更新したり、削除したりする場合は、ゴミ処理が必要です。
exec   ctx_ddl.optimize_index('myidx'、'full') 提案を実施する:毎日システムが暇な時に全文索引を相応する最適化を行い、検索の効率を高める。
P.S.タイミング最適化インデックス
3.タイミング最適化同期ドメインインデックス タイミングタスクを作成し、定期的にフィールドインデックスを最適化します。
SQL> create or replace procedure hsp_sync_index as
  2  begin
  3  ctx_ddl.sync_index('id_cont_msg');
  4  end;
  5  /

Procedure created.

Elapsed: 00:00:00.08
SQL> VARIABLE jobno number;  
SQL> BEGIN
   2 DBMS_JOB.SUBMIT(:jobno,'hsp_sync_index();',  
   3 SYSDATE, 'SYSDATE + (1/24/4)');  
   4 commit;  
   5 END;  
   6 /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.27
SQL> create or replace procedure hsp_optimize_index as
  2  begin
  3  ctx_ddl.optimize_index('id_cont_msg','FULL');
  4  end;
  5  /

SQL> VARIABLE jobno number;  
SQL> BEGIN
   2 DBMS_JOB.SUBMIT(:jobno,'hsp_optimize_index();',  
   3 SYSDATE, 'SYSDATE + 1');  
   4 commit; 
   5 END;
   6 /
Procedure created.

Elapsed: 00:00:00.03

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.02
SQL>