Oracle的全文检索实现逻辑,通过lexer词法分析器,把值的term找出来。相对于使用like,或者instr函数,速度有着明显的优势。但是因为分词,所以会占用的一定的空间。如果空间足够以及对速度有一样的需求,可以考虑全文检索。
ALTER ${用户} CTXSYS ACCOUNT UNLOCK;
grant execute on ctx_ddl to ${用户}
oracle text中的分析器有3种:
1. basic_lexer:
针对英文,只能根据空格和标点来进行拆分。比如“中国深圳”,只能拆分为“中国深圳”一个词,根据“中国”或者“深圳”就搜索不到。
2. chinese_vgram_lexer:
专门的汉语分析器,按字单元进行拆分,比如“中国深圳”,可以拆分为“中”、“中国“、”国深”、“深圳”、“圳”五个词组。这种方式的好处是能够将所有有可能的词组全部保存进索引表,使得数据不会遗漏,但是效率上来说就差强人意了。
3. chinese_lexer:
一种新的汉语分析器,能够认识大部分常用的汉语词汇,较与chinese_vgram_lexer机械式的拆分,能够按常用词汇进行拆分存储。比如“中国深圳”,只会被拆分为“中国”、“深圳”两个词组,但是精确度没有上一个分析器高。
指定分析器代码如下:其中my_lexer是自定义的分析器名
BEGIN
ctx_ddl.create_preference ('my_lexer', 'chinese_lexer');
END;
在我们建索引的时候,通常需要对一些常用的词组进行过滤,比如对公司名称进行检索时,肯定不希望输入“有限公司”、“公司”等关键词时,也会有搜索结果。
创建过滤词组:
exec ctx_ddl.create_stoplist('my_stoplist');
自定义需要过滤的词组内容:
ctx_ddl.add_stopword('my_stoplist','有限公司');
ctx_ddl.add_stopword('my_stoplist','股份有限公司');
意思就是,创建了一个名为“my_stoplist”的过滤词组,“有限公司”、“股份有限公司”这两个词组不会被创建为索引。
对指定列建立全文索引:
create index INX_ATTRIBUTION on gsmdata(ATTRIBUTION) indextype is
CTXSYS.CONTEXT parameters('lexer my_lexer stoplist my_stoplist');
注释版:
CREATE INDEX ${INDEX_NAME} ON ${TABLE_NAME}(${CLOUM_NAME}) indextype
is ctxsys.context parameters('lexer ${分析器} stoplist ${过滤词组}');
总结:在gsmdata表中的ATTRIBUTION字段上创建索引,索引类系那个为context类型,该索引用到的分析器为前面定义的my_lexer,该索引用到的过滤词组为前面定义得my_stoplist。
1.查询该索引的所有相关信息:
select * from user_indexes where index_name = 'INDEXS_NAME';--//查询的信息更详细
select * from user_ind_columns where index_name = 'INDEXS_NAME';
2.查询表建立了哪些索引:
select index_name from dba_indexes where table_name='TABLE_NAME'
使用全文索引:
select * from gsmdata where contains(ATTRIBUTION,'电信')>0
使用oracle自带操作:
SELECT * FROM gsmdata WHERE INSTR (ATTRIBUTION, '电信') > 0;
SELECT * FROM gsmdata WHERE ATTRIBUTION LIKE '%电信%';
对表的dml操作是不会更新全文索引的,这个也是全文索引的一个特点,索引我们必须手动去维护索引,具体写法如下:
execctx_ddl.sync_index('${索引字段}');--同步索引,将新的数据同步到索引
exec ctx_ddl.optimize_index('${索引字段}','FULL');--优化索引
1.创建日志记录表–记录同步与优化操作
create table JOBTEST (ID DATE, CONTENT VARCHAR2(200));
2.创建 同步存储过程 (PROC_SYNC_INDEX为该同步的自定义名称)
create or replace procedure PROC_SYNC_INDEX
is
begin
ctx_ddl.sync_index('INDEX_NAME');--//执行同步全文索引
insert into JOBTEST values(SYSDATE, '同步任务于'||SYSDATE||'执行');
end;
3.创建同步优化存储过程, (PROC_SYNC_OPTIMIZE=优化的自定义名称,INDEX_NAME=索引名称)
create or replace procedure PROC_SYNC_OPTIMIZE
is
begin
ctx_ddl.sync_index('INDEX_NAME');
ctx_ddl.optimize_index('INDEX_NAME','FULL');--//执行同步优化索引
insert into JOBTEST values(SYSDATE, '同步优化任务于'||SYSDATE||'执行');
end;
4.查看/删除存储过程
--//查看创建的存储过程
select * from user_procedures;
--//删除存储过程(PROC_SYNC_INDEX=上面的存储过程的名称)
DROP PROCEDURE PROC_SYNC_INDEX
5.创建同步定时任务
DECLARE
X NUMBER;//定时器的id
BEGIN
SYS.DBMS_JOB.SUBMIT
(
job => X --//输出变量,是此任务在任务队列中的编号
,what => 'PROC_SYNC_INDEX;' --//执行的任务的名称及其输入参数
,next_date => SYSDATE --//任务执行的时间,一般为当前时间
,interval => 'TRUNC(SYSDATE + 1)' --//任务执行的时间间隔,这个就是每天午夜12点同步
);
END;
6.创建优化定时任务
DECLARE
X NUMBER;
BEGIN
SYS.DBMS_JOB.SUBMIT
(
job => X --//输出变量,是此任务在任务队列中的编号
,what => 'PROC_SYNC_OPTIMIZE;' --//执行的任务的名称及其输入参数
,next_date => SYSDATE --//任务执行的时间,一般为当前时间
,interval => 'TRUNC(SYSDATE + 1)' --//任务执行的时间间隔,这个就是每天午夜12点同步
);
END;
7.查看同步与优化的日志/执行job详情
select * from JOBTEST --//查看同步与优化的操作日志
select * from user_jobs; --//查看调度任务(同步与优化等多个任务的详情表)
select * from dba_jobs_running; --//查看正在执行的所有调度任务
select * from dba_jobs; --//查看执行完的调度任务
8.删除定时器job
BEGIN
/*23为job的id,此id不是随便填写的,而是执行select * from user_jobs;查询到定时任务名称对应的id*/
dbms_job.remove(23);
END;
9.job创建成功却不执行
原因:如果创建存储过程,执行job都没有出问题,那么大概率就是ORACLE默认的定时任务执行范围等于“0”或者设置太小,需要重新进行设置。
--//查看oracle默认的定时任务执行范围
select value from v$parameter where name like '%job_queue_processes%'
--//修改定时任务执行范围
alter system set job_queue_processes =1000;
interval 参数 是一个表示Oracle合法日期表达式的字符串。
1.设置固定的运行时间间隔
每天运行一次 'SYSDATE + 1'
每小时运行一次 'SYSDATE + 1/24'
每1分钟运行一次 'SYSDATE + 1/24/60'
每10分钟运行一次 'SYSDATE + 10/(60*24)'
每30秒运行一次 'SYSDATE + 30/(60*24*60)'
每隔一星期运行一次 'SYSDATE + 7'
不再运行该任务并删除它 'NULL'
2,设置特定的运行时间间隔
Interval => TRUNC(sysdate,’mi’) + 1 / (24*60) //每分钟执行
Interval =>TRUNC(SYSDATE + 1) //每天午夜12点
Interval => TRUNC(sysdate) + 1 +2 / (24) //每天的凌晨2点执行
Interval => TRUNC(SYSDATE + 1) + (8*60+30)/(24*60) //每天早上8点30分
Interval => NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24//每星期二中午12点
Interval => TRUNC(LAST_DAY(SYSDATE ) + 1) //每个月第一天的午夜12点
Interval => TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24 //每个季度最后一天的晚上11点
Interval => TRUNC(LEAST(NEXT_DAY(SYSDATE, ''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)//每星期六和日早上6点10分
3.job的运行频率设置
时间 | 代码 |
---|---|
每天 | trunc(sysdate+1) |
每周 | trunc(sysdate+7) |
每月 | trunc(sysdate+30) |
每个星期日 | next_day(trunc(sysdate),‘星期日’) |
每天6点 | trunc(sysdate+1)+6/24) |
每半个小时 | sysdate+30/(24*60) |
每个小时的第15分钟运行 | trunc(sysdate,‘hh’)+(60+15)/(24*60)) |
每天固定时间–比如早上8:10分钟 | Trunc(Sysdate+1) + (860+10)/2460 |
综合整理了大部分关于全文索引相关的知识点,希望对大家有用,如有错误望指正。