不使用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; |
步驟三 設定詞法分析器(lexer)
Oracle實現全文檢索索引,其機制其實很簡單。即通過Oracle專利的詞法分析器(lexer),將文章中所有的表意單元(Oracle 稱為 term)找出來,記錄在一組 以dr$開頭的表中,同時記下該term出現的位置、次數、hash 值等資訊。檢索時,Oracle 從這組表中尋找相應的term,並計算其出現頻率,根據某個演算法來計算每個文檔的得分(score),即所謂的‘匹配率’。而lexer則是該機制的核心,它決定了全文檢索索引的效率。Oracle 針對不同的語言提供了不同的 lexer, 而我們通常能用到其中的三個:
n basic_lexer: 針對英語。它能根據空格和標點來將英語單詞從句子中分離,還能自動將一些出現頻率過高已經失去檢索意義的單詞作為‘垃圾’處理,如if , is 等,具有較高的處理效率。但該lexer應用於漢語則有很多問題,由於它只認空格和標點,而漢語的一句話中通常不會有空格,因此,它會把整句話作為一個term,事實上失去檢索能力。以‘中國人民站起來了’這句話為例,basic_lexer 分析的結果只有一個term ,就是‘中國人民站起來了’。此時若檢索‘中國’,將檢索不到內容。
n chinese_vgram_lexer: 專門的漢語分析器,支援所有漢字字元集(ZHS16CGB231280 ZHS16GBK ZHT32EUC ZHT16BIG5 ZHT32TRIS ZHT16MSWIN950 ZHT16HKSCS UTF8 )。該分析器按字為單元來分析漢語句子。‘中國人民站起來了’這句話,會被它分析成如下幾個term: ‘中’,‘中國’,‘國人’,‘人民’,‘民站’,‘站起’,起來’,‘來了’,‘了’。可以看出,這種分析方法,實現演算法很簡單,並且能實現‘一網打盡’,但效率則是差強人意。
n chinese_lexer: 這是一個新的漢語分析器,只支援utf8字元集。上面已經看到,chinese vgram lexer這個分析器由於不認識常用的漢語詞彙,因此分析的單元非常機械,像上面的‘民站’,‘站起’在漢語中根本不會單獨出現,因此這種term是沒有意義的,反而影響效率。chinese_lexer的最大改進就是該分析器 能認識大部分常用漢語詞彙,因此能更有效率地分析句子,像以上兩個愚蠢的單元將不會再出現,極大 提高了效率。但是它只支援 utf8, 如果你的資料庫是zhs16gbk字元集,則只能使用笨笨的那個Chinese vgram lexer.
如果不做任何設定,Oracle 預設使用basic_lexer這個分析器。要指定使用哪一個lexer, 可以這樣操作:
第一. 目前使用者下下建立一個preference(例:在pomoho使用者下執行以下語句)
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作為分析器。
步驟四 建立索引
通過以下文法建立全文索引
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')
|
步驟五 使用索引
使用全文索引很簡單,可以通過:
select * from pubmenu where contains(menuname,'上傳圖片')>0
全文索引的種類
建立的Oracle Text索引被稱為域索引(domain index),包括4種索引類型:
l CONTEXT
2 CTXCAT
3 CTXRULE
4 CTXXPATH
依據你的應用程式和文本資料類型你可以任意選擇一種。
對多欄位建立全文索引
很多時候需要從多個文字欄位中查詢滿足條件的記錄,這時就需要建立針對多個欄位的全文索引,例如需要從pmhsubjects(專題表)的subjectname(專題名稱)和briefintro(簡介)上進行全文檢索索引,則需要按以下步驟進行操作:
Ø 建議多欄位索引的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
|
全文索引的維護
對於CTXSYS.CONTEXT索引,當應用程式對基表進行DML操作後,對基表的索引維護是必須的。索引維護包括索引同步和索引最佳化。
在索引建好後,我們可以在該使用者下查到Oracle自動產生了以下幾個表:(假設索引名為myindex):
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、update、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類型的索引來說, 當對基表進行DML操作的時候,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 。 |
指定一個大的記憶體時候可以加快索引效率和查詢速度,且索引有較少的片段
part_name 同步哪個分區索引。
parallel_degree 並行同步索引。設定並行度。
例如:
同步索引myindex:Exec ctx_ddl.sync_index ('myindex');
實施建議:建議通過oracle的job對索引進行同步
索引的最佳化
經常的索引同步將會導致你的CONTEXT索引產生片段。索引片段嚴重的影響了查詢的反應速度。你可以定期最佳化索引來減少片段,減少索引大小,提高查詢效率。
當文本從表中刪除的時候,Oracle Text標記刪除的文檔,但是並不馬上修改索引。因此,就的文檔資訊佔據了不必要的空間,導致了查詢額外的開銷。你必須以FULL模式最佳化索引,從索引中刪除無效的舊的資訊。這個過程叫做垃圾處理。當你經常的對錶文本資料進行更新,刪除操作的時候,垃圾處理是很必要的。
exec ctx_ddl.optimize_index ('myidx', 'full');
實施建議:每天在系統閒置時候對全文索引進行相應的最佳化,以提高檢索的效率
- Oracle資料庫管理指令碼淺析
- 使用度量基準技術實現Oracle自我監控
- 詳解Oracle建立使用者和對使用者的管理