由於工作需要筆者在HP UX Soralis 上面設置了Oracle Intermedia來實現全文檢索目前已經投入實際使用設置過程中有許多問題和經驗拿來和大家交流本文依據的是Oracle 和兩個版本不能保證適用於其他版本
目前全文檢索功能幾乎所有主流數據庫都支持此前筆者曾在sql server 上實現感覺非常簡單方便但創建全文檢索索引的時間比較長通常要十幾個小時Oracle 的全文檢索建立和維護索引都要快得多筆者的萬記錄的一個表建立索引只需要分鐘同步一次只需要分鐘但設置就要復雜得多
一設置過程
首先檢查你的數據庫是否安裝了intermedia
這可以通過檢查是否有ctxsys用戶和ctxapp角色(role) 如果沒有這個用戶和角色意味著你的數據庫創建時未安裝intermedia功能你必須修改數據庫以安裝這項功能
修改過程
運行 $ORACLE_HOME/bin/dbassist 選擇modify database 然後在選擇數據庫功能時將j server 和 intermedia 都選上(安裝intermedia必須同時安裝jserver)強烈建議你在做這個改動前先備份整個數據庫
設置extproc
Oracle 是通過所謂的外部調用功能(external procedure)來實現intermedia的因此正確地設置extproc是關鍵一步
首先要配置listener 使它能監聽intermedia 調用的請求你可以通過運行$ORACLE_HOME/bin/netassit 來進行配置也可以手工修改配置文件$ORACLE_HOME/network/admin/listenerora 然後重新啟動listener下面以一個例子來講述如何手工修改配置文件
打開listenerora文件在修改前通常有如下內容(假定使用缺省listener)
LISTENER =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = MYDATABASE)(PORT = ))
)
SID_LIST_LISTENER =
(SID_DESC =
(GLOBAL_DBNAME = mydatabaseworld)
(ORACLE_HOME = /u/app/oracle/product/)
(SID_NAME = mydatabase)
)
這個listener還沒有配置extproc 因此需要為它增加對extproc的監聽辦法就是分別增加description 和 sid_desc 修改後的listnerora 如下
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = MYDATABASE)(PORT = ))
)
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = mydatabaseworld)
(ORACLE_HOME = /u/app/oracle/product/)
(SID_NAME = mydatabase)
)
(SID_DESC =
(PROGRAM = extproc)
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u/app/oracle/product/)
)
)
注意上面的host global_dbnamesid_nameoracle_home應填寫你的數據庫的實際值但program一項必須填寫extproc
其次要配置服務器端的tnsnamesora文件該文件的位置在$ORACLE_HOME/network/admin下面同樣可以通過運行netasst來進行配置
在tnsnamesora文件中需要增加如下一項
EXTPROC_CONNECTION_DATAEXTPROC_CONNECTION_DATAWORLD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(CONNECT_DATA =
(SID = PLSExtProc)
)
)
注意其中KEY 和SID必須與listenerora中的key 和sid_name對應相同
修改完成後重新啟動listener (先用lsnrctl stop 然後 lsnrctl start) 然後使用tnsping 來測試一下是否配置正確
tnsping extproc_connection_data 或者
tnsping extproc_connection_dataworld如果配置正確會顯示
Attempting to contact (ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC)) OK(毫秒)
否則請檢查你的上述兩個文件並注意在修改後一定要重新啟動listener但並不需要重新啟動數據庫
設置詞法分析器(lexer)
Oracle實現全文檢索其機制其實很簡單即通過Oracle專利的詞法分析器(lexer)將文章中所有的表意單元(Oracle 稱為 term) 找出來記錄在一組 以 dr$開頭的表中同時記下該term出現的位置次數hash 值等信息檢索時Oracle 從這組表中查找相應的 term並計算其出現頻率根據某個算法來計算每個文檔的得分(score)即所謂的匹配率而lexer則是該機制的核心它決定了全文檢索的效率Oracle 針對不同的語言提供了不同的 lexer 而我們通常能用到其中的三個
basic_lexer 針對英語它能根據空格和標點來將英語單詞從句子中分離還能自動將一些出現頻率過高已經失去檢索意義的單詞作為垃圾處理如if is 等具有較高的處理效率但該lexer應用於漢語則有很多問題由於它只認空格和標點而漢語的一句話中通常不會有空格因此它會把整句話作為一個term事實上失去檢索能力以中國人民站起來了這句話為例basic_lexer 分析的結果只有一個term 就是中國人民站起來了此時若檢索中國將檢索不到內容
chinese_vgram_lexer 專門的漢語分析器支持所有漢字字符集該分析器按字為單元來分析漢語句子中國人民站起來了這句話會被它分析成如下幾個term 中中國國人人民民站站起起來來了了可以看出這種分析方法實現算法很簡單並且能實現一網打盡但效率則是差強人意
chinese_lexer 這是一個新的漢語分析器只支持utf字符集上面已經看到chinese vgram lexer這個分析器由於不認識常用的漢語詞匯因此分析的單元非常機械像上面的民站站起在漢語中根本不會單獨出現因此這種term是沒有意義的反而影響效率chinese_lexer的最大改進就是該分析器 能認識大部分常用漢語詞匯因此能更有效率地分析句子像以上兩個愚蠢的單元將不會再出現極大 提高了效率但是它只支持 utf 如果你的數據庫是zhsgbk字符集則只能使用笨笨的那個Chinese vgram lexer
如果不做任何設置Oracle 缺省使用basic_lexer這個分析器要指定使用哪一個lexer 可以這樣操作
第一在ctxsys用戶下建立一個preference
begin ctx_ddlcreate_preference(my_lexerchinese_vgram_lexer) end
第二在建立intermedia索引時指明所用的lexer
create index myindex on mytable(mycolumn) indextype is ntext
parameters(lexer my_lexer)
這樣建立的全文檢索索引就會使用chinese_vgram_lexer作為分析器
使用job定時同步和優化
在intermedia索引建好後如果表中的數據發生變化比如增加或修改了記錄怎麼辦?由於對表所發生的任何dml語句都不會自動修改索引因此必須定時同步(sync)和優化(optimize)索引以正確反映數據的變化
在索引建好後我們可以在該用戶下查到Oracle自動產生了以下幾個表(假設索引名為myindex)
DR$myindex$IDR$myindex$KDR$myindex$RDR$myindex$N
其中以I表最重要可以查詢一下該表看看有什麼內容
select token_text token_count from DR$I_RSK$I where rownum<=
這裡就不列出查詢接過了可以看到該表中保存的其實就是Oracle 分析你的文檔後生成的term記錄在這裡包括term出現的位置次數hash值等當文檔的內容改變後可以想見這個I表的內容也應該相應改變才能保證Oracle在做全文檢索時正確檢索到內容(因為所謂全文檢索其實核心就是查詢這個表)那麼如何維護該表的內容呢?總不能每次數據改變都重新建立索引吧!這就用到sync 和 optimize了
同步(sync)將新的term 保存到I表
優化(optimize)清除I表的垃圾主要是將已經被刪除的term從I表刪除
Oracle提供了一個所謂的ctx server來做這個同步和優化的工作只需要在後台運行這個進程它會監視數據的變化及時進行同步但筆者使用ctxserver碰到了許多問題Oracle 北京的support也建議不使用而是用以下的兩個job來完成(該job要建在和表同一個用戶下)
sync:
VARIABLE jobno number;
BEGIN
DBMS_JOBSUBMIT(:jobnoctx_ddlsync_index(myindex);
SYSDATE SYSDATE + (//));
commit;
END;
optimizer
VARIABLE jobno number;
BEGIN
DBMS_JOBSUBMIT(:jobnoctx_ddloptimize_index(myindexFULL);
SYSDATE SYSDATE + );
commit;
END;
其中 第一個job的SYSDATE + (//)是指每隔分鐘同步一次第二個job的SYSDATE + 是每隔天做一次全優化具體的時間間隔你可以根據自己的應用的需要而定至此你的全文檢索功能已設置完成
二常見錯誤
下面就一些常見的錯誤信息給出解釋和解決辦法
sync 失敗
DRG ALTER INDEX T_DOC_CT失敗
DRG oracle error in drsxsopen
ORA STR 賦值變量缺少空後綴
解決這是i的一個bug 但可以避免它方法是在同步之前先發一個語句
alter session set nls_language=American
create index 失敗
ORA 執行 ODCIINDEXCREATE 例行程序時出錯
ORA interMedia Text 錯誤
ORA 在CTXSYSDRUE line
ORA 在CTXSYSTEXTINDEXMETHODS line
ORA 在line
解決這是之前的版本的一個bug 在處理中文時某個特殊字符造成的向Oracle要補丁或者自己去 下載(需要CSI 號碼)
create index 失敗
RA 執行 ODCIINDEXCREATE 例行程序時出錯
ORA interMedia Text 錯誤
DRG Net 監聽器沒有運行或無法啟動外部過程
ORA 無法打開與外部過程代理程序的 RPC 連接
ORA 在CTXSYSDRUE line
ORA 在CTXSYSTEXTINDEXMETHODS line
ORA 在line
解決明顯的extproc配置不當仔細閱讀本文基本設置的第二步
訪問建有索引的表時失敗
ora 域索引標記為loading/failed/unusable
解決這是該表的一個intermedia索引有問題該索引要麼沒有正確建立要麼是某次同步失敗導致它狀態異常先查到是哪個索引
Select idx_nameidx_status from ctxsysctx_indexes
然後同步該索引或者強制刪除它
重建alter index myindex rebuild online parameters(sync)
刪除drop index myindex force
使用chinese_lexer失敗
ERROR at row
ORA err on ODCIINDEXCREATE
ORA interMedia Text err
DRG index is not existing
DRG the lexer cannt analyze as SIMPLIFIED CHINESE_CHINAZHSGBK
ORA 在CTXSYSDRUE line
ORA 在CTXSYSTEXTINDEXMETHODS line
ORA 在line
解決chinese_lexer 只支持utf字符集現在你面臨抉擇忍受chinese vgram lexer的愚蠢或者將數據庫字符集改到 utf 但面對可能引起你的應用不能正確處理中文的風險(先咨詢Oracle support 並且與你的應用軟件提供商聯系)
升級或應用patch後失敗
ORA err when execute ODCIINDEXDROP
ORA interMedia Texterr
ORA PL/SQL can not find program unit beingcalled
ORA at CTXSYSDRUE line
ORA atCTXSYSTEXTINDEXMETHODS line
ORA at line
解決這是intermedia的某個object 沒有正確產生或者編譯用ctxsys用戶登錄後運行 $oracle_home/ctx/admin/drpkhsql 和 $oracle_home/ctx/admin/drplbsql 以重新產生所有的package你也可以直接察看dba_objects視圖找出那些屬於ctxsys用戶並且status 為invalid的東西重新產生或者重新編譯(你可能會發現有許多這種東西不要驚訝Oracle不會因此而崩潰)
create index 失敗
ERROR 位於第 行
ORA 執行 ODCIINDEXCREATE 例行程序時出錯
ORA interMedia Text 錯誤
DRG oracle error in driddlIndexResume
ORA 在嘗試分配 字節 (cursor work heQERHJ Bit vector)時進程內存不足
ORA 在CTXSYSDRUE line
ORA 在CTXSYSTEXTINDEXMETHODS line
ORA 在line
解決引起這個問題可以有多種原因首先你可以將sort_area_size這個參數減小到不多於M這可以防止Oracle在創建索引時分配太多的sort 內存而耗盡資源 但如果這不起作用而且你是 則恭喜你hit 了bug 該bug 在你要建索引的字段如果某條記錄的長度超過字符時引起Oracle耗盡內存資源別無它法除了打 B 的補丁
From:http://tw.wingwit.com/Article/program/Oracle/201311/17277.html