Oracle 全文检索(Oracle Text)

Oracle 全文检索(Oracle Text)

适用版本:Oracle Database 9i / 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

Oracle Text 提供全文检索能力[1]:

特点

  • 全文搜索
  • 模糊匹配
  • 多语言
  • 文档检索

2. 索引类型

类型说明
CONTEXT文本列(CLOB/VARCHAR2)
CTXCAT目录项搜索
CTXRULE查询规则
CTXXPATHXML 搜索

3. CONTEXT 索引

3.1 创建

CREATE INDEX idx_emp_resume ON employees(resume) 
INDEXTYPE IS CTXSYS.CONTEXT;

3.2 查询

-- CONTAINS
SELECT * FROM employees 
WHERE CONTAINS(resume, 'Oracle') > 0;

-- 多词
SELECT * FROM employees 
WHERE CONTAINS(resume, 'Oracle AND Java') > 0;

-- 或
SELECT * FROM employees 
WHERE CONTAINS(resume, 'Oracle OR MySQL') > 0;

-- 模糊
SELECT * FROM employees 
WHERE CONTAINS(resume, 'fuzzy(Oracle)') > 0;

-- 通配符
SELECT * FROM employees 
WHERE CONTAINS(resume, 'Ora%') > 0;

3.3 查询分数

SELECT 
  employee_id,
  SCORE(1) AS score
FROM employees
WHERE CONTAINS(resume, 'Oracle', 1) > 0
ORDER BY score DESC;

4. 操作符

4.1 逻辑

OR  / |
AND / &
NOT / -

4.2 NEAR

-- 相邻
WHERE CONTAINS(resume, 'Oracle NEAR Java') > 0;

4.3 短语

-- 精确短语
WHERE CONTAINS(resume, '"Oracle Database"') > 0;

4.4 模糊

-- fuzzy
WHERE CONTAINS(resume, 'fuzzy(Oracle)') > 0;

-- soundex(发音相似)
WHERE CONTAINS(resume, '!Smith') > 0;

-- stem(词干)
WHERE CONTAINS(resume, '$run') > 0;
-- running, runs 等

5. 索引同步

5.1 自动同步

-- ON COMMIT
CREATE INDEX idx_emp_resume ON employees(resume) 
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('SYNC (ON COMMIT)');

-- 定时
CREATE INDEX idx_emp_resume ON employees(resume) 
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('SYNC (EVERY "SYSDATE+1/24")');

5.2 手动同步

EXEC CTX_DDL.SYNC_INDEX('idx_emp_resume');

5.3 优化

-- 重建
ALTER INDEX idx_emp_resume REBUILD;

-- 优化
EXEC CTX_DDL.OPTIMIZE_INDEX('idx_emp_resume', 'FULL');

6. CTXCAT 索引

6.1 创建

BEGIN
  CTX_DDL.CREATE_INDEX_SET('emp_iset');
  CTX_DDL.ADD_INDEX('emp_iset', 'dept_id');
END;
/

CREATE INDEX idx_emp_cat ON employees(resume) 
INDEXTYPE IS CTXSYS.CTXCAT
PARAMETERS ('INDEX SET emp_iset');

6.2 查询

SELECT * FROM employees 
WHERE CATSEARCH(resume, 'Oracle', 'dept_id = 10') > 0;

7. 多列索引

-- 多列索引
CREATE INDEX idx_emp_multi ON employees(resume, job_desc) 
INDEXTYPE IS CTXSYS.CONTEXT
FILTER BY dept_id;

8. 词法分析

8.1 中文分词

BEGIN
  CTX_DDL.CREATE_PREFERENCE('my_lexer', 'CHINESE_LEXER');
END;
/

CREATE INDEX idx_emp_resume ON employees(resume) 
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('LEXER my_lexer');

8.2 自定义词库

BEGIN
  CTX_DDL.CREATE_STOPLIST('my_stop');
  CTX_DDL.ADD_STOPWORD('my_stop', 'the');
  CTX_DDL.ADD_STOPWORD('my_stop', 'a');
END;
/

CREATE INDEX idx_emp_resume ON employees(resume) 
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('STOPLIST my_stop');

9. 文档检索

9.1 二进制文档

-- BLOB 存储文档
CREATE TABLE docs (
  id NUMBER,
  content BLOB
);

-- 自动过滤
CREATE INDEX idx_docs ON docs(content) 
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('FILTER CTXSYS.AUTO_FILTER');

9.2 查询

SELECT id FROM docs WHERE CONTAINS(content, 'Oracle') > 0;

10. 应用场景

10.1 简历搜索

CREATE INDEX idx_resume ON candidates(resume) 
INDEXTYPE IS CTXSYS.CONTEXT;

SELECT * FROM candidates 
WHERE CONTAINS(resume, 'Java AND Spring') > 0
ORDER BY SCORE(1) DESC;

10.2 商品搜索

CREATE INDEX idx_product ON products(description) 
INDEXTYPE IS CTXSYS.CONTEXT;

SELECT * FROM products 
WHERE CONTAINS(description, '手机') > 0;

10.3 文档管理

-- PDF/Word 检索
CREATE INDEX idx_doc ON documents(content) 
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('FILTER CTXSYS.AUTO_FILTER');

SELECT * FROM documents 
WHERE CONTAINS(content, '合同') > 0;

11. 常见坑与排错

11.1 ORA-29871: 索引未同步

-- 同步索引
EXEC CTX_DDL.SYNC_INDEX('idx_name');

11.2 查询无结果

-- 1. 索引未同步
-- 2. 词法分析问题
-- 3. 大小写
-- 4. 停用词

11.3 性能差

-- 1. 优化索引
EXEC CTX_DDL.OPTIMIZE_INDEX('idx_name', 'FULL');
-- 2. 限制结果
-- 3. 加 SCORE 排序

11.4 中文分词

-- 使用 CHINESE_LEXER
-- 或 CHINESE_VGRAM_LEXER

12. 最佳实践

  1. CONTEXT 索引:文本列
  2. CTXCAT 索引:目录搜索
  3. 自动同步:ON COMMIT
  4. 定期优化:性能
  5. 中文用 CHINESE_LEXER:分词
  6. SCORE 排序:相关性
  7. 停用词表:减少索引
  8. 多列索引:综合搜索
  9. AUTO_FILTER:文档检索
  10. 监控索引:状态

13. 参考资料

[1] Oracle Text Reference 19c https://docs.oracle.com/en/database/oracle/oracle-database/19/ccref/