oracle 全文索引

--模糊查询的两种方式
select * from dj_nsrxx where contains(nsrmc,'和谦亨') > 0;
select * from dj_nsrxx where nsrmc like '%康仁如快餐店%';

--建立分词器
BEGIN
ctx_ddl.create_preference ('my_chinese_vgram_lexer', 'chinese_vgram_lexer');
END;

--建立索引
CREATE INDEX IDX_DJ_NSRXX_NSRMC_QW ON dj_nsrxx(nsrmc) indextype is ctxsys.context parameters('lexer my_chinese_vgram_lexer');
--使用实时同步(DML提交时同步全文索引)
CREATE INDEX IDX_DJ_NSRXX_NSRMC_QW ON dj_nsrxx(nsrmc) indextype is ctxsys.context PARAMETERS ('LEXER my_chinese_vgram_lexer SYNC (ON COMMIT)');

--刷新索引
BEGIN
   ctx_ddl.sync_index('IDX_DJ_NSRXX_NSRMC_QW');
end;

--定时job刷新索引,未测试
BEGIN
   DBMS_JOB.SUBMIT(:jobno,ctx_ddl.sync_index('IDX_DJ_NSRXX_NSRMC_QW'),SYSDATE, SYSDATE + (1/24/4));
   commit;
END; 

--查询索引产生的表
select * from dba_tables where table_name like '%IDX_DJ_NSRXX_NSRMC_QW%'
select count(*) from DR$IDX_DJ_NSRXX_NSRMC_QW$I

--删除索引
drop index IDX_DJ_NSRXX_NSRMC_QW;

--删除分词器
begin
ctx_ddl.drop_preference('my_chinese_vgram_lexer');
end;

--查询索引
select * from dba_indexes;
item chinese_vgram chinese comments
测试数据量 80万 80万
创建时间 37s 370S
刷新时间(0条跟新) 0s 0s 增量刷新,刷新速度较快
刷新时间(3条跟新) 0.031S 0.031S
索引条数 123万 68万

==注:
如果一个列没有使用全文索引,而使用了contains的话会报错 column is not indexed
select * from dj_nsrxx where contains(nsrmc,’易家联快餐店’) > 0;==

以下为网上摘取的内容,简单的描述了oracle全文索引的原理


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:专门的汉语分析器,支持所有汉字字符集(ZHS16CGB231280ZHS16GBKZHT32EUCZHT16BIG5ZHT32TRISZHT16MSWIN950ZHT16HKSCSUTF8)。该分析器按字为单元来分析汉语句子。‘中国人民站起来了’这句话,会被它分析成如下几个term: ‘中’,‘中国’,‘国人’,‘人民’,‘民站’,‘站起’,起来’,‘来了’,‘了’。可以看出,这种分析方法,实现算法很简单,并且能实现‘一网打尽’,但效率则是差强人意。
chinese_lexer:这是一个新的汉语分析器,只支持utf8字符集。上面已经看到,chinese vgram lexer这个分析器由于不认识常用的汉语词汇,因此分析的单元非常机械,像上面的‘民站’,‘站起’在汉语中根本不会单独出现,因此这种term是没有意义的,反而影响效率。chinese_lexer的最大改进就是该分析器能认识大部分常用汉语词汇,因此能更有效率地分析句子,像以上两个愚蠢的单元将不会再出现,极大提高了效率。但是它只支持utf8,如果你的数据库是zhs16gbk字符集,则只能使用笨笨的那个Chinese vgram lexer.
==如果不做任何设置,Oracle缺省使用basic_lexer这个分析器。要指定使用哪一个lexer,可以这样操作:==

BEGIN
ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer');
END;

其中my_lexer是分析器名。

在索引建好后,我们可以在该用户下查到Oracle自动产生了以下几个表:(假设索引名为myindex):
DR myindex I、DR myindex K、DR myindex R、DR myindex N其中以I表最重要,可以查询一下该表,看看有什么内容:
SELECT token_text, token_count FROM dr irsk1 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对索引进行同步


instr函数在Oracle/PLSQL中是返回要截取的字符串在源字符串中的位置。instr是一个非常好用的字符串处理函数,几乎所有的字符串分隔都用到此函数。

你可能感兴趣的:(数据库)