Oracle全文檢索技術經歷演進:Oracle 8i之前稱Oracle ConText Cartridge,8/8i時期為Oracle interMedia Text,9i起更名為Oracle Text,賦予資料庫強大的文本檢索與智慧管理能力。
使用Oracle Text需具備CTXAPP角色或為CTXSYS使用者。CTXAPP可執行:建立索引、管理Text資料字典、查詢、使用PL/SQL套件。
每個索引包含多個類別,每類別含預定義物件,物件再透過屬性客製化:
BASIC_STORAGE(索引表空間參數)DIRECT_DATASTORE、FILE_DATASTORE、URL_DATASTORE等7種AUTO_SECTION_GROUP、HTML_SECTION_GROUP、XML_SECTION_GROUP等BASIC_WORDLIST(詞幹/模糊查詢選項)BASIC_INDEX_SET(用於CTXCAT索引)BASIC_LEXER、CHINESE_LEXER、CHINESE_VGRAM_LEXER等8種NULL_FILTER、INSO_FILTER、CHARSET_FILTER等BASIC_STOPLIST、MULTI_STOPLISTBEGIN
-- 中文詞法分析器
CTX_DDL.DROP_PREFERENCE('cnlex');
CTX_DDL.CREATE_PREFERENCE('cnlex', 'CHINESE_LEXER');
-- 相關詞表:啟用前綴/子字串索引
CTX_DDL.CREATE_PREFERENCE('mywordlist', 'BASIC_WORDLIST');
CTX_DDL.SET_ATTRIBUTE('mywordlist', 'PREFIX_INDEX', 'TRUE');
CTX_DDL.SET_ATTRIBUTE('mywordlist', 'PREFIX_MIN_LENGTH', '1');
CTX_DDL.SET_ATTRIBUTE('mywordlist', 'PREFIX_MAX_LENGTH', '5');
CTX_DDL.SET_ATTRIBUTE('mywordlist', 'SUBSTRING_INDEX', 'YES');
END;
CREATE INDEX idx_person_desc ON personinfo(persondesc)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS (
'DATASTORE CTXSYS.DIRECT_DATASTORE
FILTER CTXSYS.NULL_FILTER
LEXER cnlex
WORDLIST mywordlist'
);
-- 關鍵:必須使用NULL_FILTER,INSO_FILTER無法支援中文全文索引
-- 同步:將新Token寫入$I表
EXEC CTX_DDL.SYNC_INDEX('idx_user_info', '20M');
-- 優化:清除已刪除Token
EXEC CTX_DDL.OPTIMIZE_INDEX('idx_user_info', 'FULL');
| 分析器 | 適用語言 | 分詞邏輯 | 優缺點 |
|---|---|---|---|
| BASIC_LEXER | 英文/西歐語 | 空白+標點分隔 | 效率高,但中文會將整句視為單一Token,失去檢索能力 |
| CHINESE_VGRAM_LEXER | 中文(所有字符集) | 雙字元重疊(N-gram) | 「一網打盡」但產生大量無意義Token(如「民站」),效率差 |
| CHINESE_LEXER | 中文(僅UTF8) | 詞彙辨識+智慧分詞 | 識別常用詞彙,移除無意義Token,效率大幅提升,推薦 |
注意:Oracle 9.2+已改善CHINESE_LEXER的字符集限制,實測可在非UTF8環境運作。
建立索引後,Oracle自動產生DR$indexname$I/K/R/N四張表,其中$I表最關鍵,儲存Token、出現位置、次數、Hash值。
建立DBMS_JOB或DBMS_SCHEDULER定期執行同步/優化,確保檢索結果即時性。
DR$indexname$I表是否存在CONTAINS查詢:SELECT * FROM personinfo WHERE CONTAINS(persondesc, '關鍵字', 1) > 0ORA-20000: DRG-10599: 列沒有編制索引則建立失敗| 測試案例 | 查詢方式 | 耗時 | 備註 |
|---|---|---|---|
| 測試一 | LIKE '%大學%' | 40.688秒 | 全表掃描 |
| 測試二 | LIKE '%1999%' | 47.218秒 | 全表掃描 |
| 測試七 | CONTAINS '1999' (CHINESE_LEXER) | 首次469ms,後續~210ms | 英文查詢極快 |
| 測試八 | CONTAINS '大學' (CHINESE_LEXER) | 首次9.359秒,後續~210ms | 中文首次較慢,但後續極快 |
| 測試九 | DBMS_LOB.INSTR '大學' (有索引) | 54.953秒 | 未使用索引,仍全表掃描 |
結論:CHINESE_LEXER配合CONTAINS查詢,中文檢索效能較LIKE提升40-200倍。但實測發現CONTAINS回傳筆數略少於LIKE,需評估業務容忍度。整體來說,Oracle中文全文索引在9i後已具備實用價值,建議生產環境採用CHINESE_LEXER+NULL_FILTER組合。